SkOpSegment.cpp revision ccec0f958ffc71a9986d236bc2eb335cb2111119
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
7ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#include "SkOpCoincidence.h"
8dac1d17027dcaa5596885a9f333979418b35001ccaryclark#include "SkOpContour.h"
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h"
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h"
11ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
12ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark/*
13ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkAfter computing raw intersections, post process all segments to:
14ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark- find small collections of points that can be collapsed to a single point
15ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark- find missing intersections to resolve differences caused by different algorithms
16ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
17ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkConsider segments containing tiny or small intervals. Consider coincident segments
18ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbecause coincidence finds intersections through distance measurement that non-coincident
19ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkintersection tests cannot.
20ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark */
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define F (false)      // discard the edge
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define T (true)       // keep the edge
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gUnaryActiveEdge[2][2] = {
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//  from=0  from=1
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//  to=0,1  to=0,1
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {F, T}, {T, F},
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = {
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//                 miFrom=0                              miFrom=1
334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org//         miTo=0             miTo=1             miTo=0             miTo=1
344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org//     suFrom=0    1      suFrom=0    1      suFrom=0    1      suFrom=0    1
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//   suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}},  // mi - su
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}},  // mi & su
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}},  // mi | su
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}},  // mi ^ su
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef F
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef T
4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
45ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr,
46ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** endPtr, bool* done, bool* sortable) {
47ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done, sortable)) {
484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return result;
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
50ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done, sortable)) {
51ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return result;
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return NULL;
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
56ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr,
57ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** endPtr, bool* done, bool* sortable) {
58ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* upSpan = start->upCastable();
59ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (upSpan) {
60ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (upSpan->windValue() || upSpan->oppValue()) {
61ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSpanBase* next = upSpan->next();
62ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!*endPtr) {
63ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                *startPtr = start;
64ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                *endPtr = next;
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
66ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!upSpan->done()) {
67ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (upSpan->windSum() != SK_MinS32) {
68ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    return spanToAngle(start, next);
694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                *done = false;
714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
73ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkASSERT(upSpan->done());
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
76ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* downSpan = start->prev();
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // edge leading into junction
78ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (downSpan) {
79ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (downSpan->windValue() || downSpan->oppValue()) {
80ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!*endPtr) {
81ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                *startPtr = start;
82ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                *endPtr = downSpan;
83ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
84ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!downSpan->done()) {
85ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (downSpan->windSum() != SK_MinS32) {
86ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    return spanToAngle(start, downSpan);
874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                *done = false;
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
91ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkASSERT(downSpan->done());
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return NULL;
954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
97ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr,
98ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** endPtr, bool* done, bool* sortable) {
99ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpPtT* oPtT = start->ptT()->next();
100ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = oPtT->segment();
101ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* oSpan = oPtT->span();
102ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable);
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
105ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) {
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(!done());
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // see if either end is not done since we want smaller Y of the pair
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool lastDone = true;
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double lastT = -1;
111ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* span = &fHead;
112ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
113ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (lastDone && (span->final() || span->upCast()->done())) {
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            goto next;
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        {
117ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const SkPoint& xy = span->pt();
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) {
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                topPt = xy;
120ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (firstSpan) {
121ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    *firstSpan = span;
12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                }
12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (fVerb != SkPath::kLine_Verb && !lastDone) {
125ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPts, lastT,
126ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        span->t());
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                        && topPt.fX > curveTop.fX)) {
12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    topPt = curveTop;
130ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (firstSpan) {
131ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        *firstSpan = span;
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    }
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                }
13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
135ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            lastT = span->t();
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comnext:
138ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (span->final()) {
139ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            break;
140ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
141ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        lastDone = span->upCast()->done();
142ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((span = span->upCast()->next()));
14307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return topPt;
14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
146ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask,
147ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkPathOp op) {
148ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumMiWinding = this->updateWinding(end, start);
149ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumSuWinding = this->updateOppWinding(end, start);
15065f553182ab7069378ef863d30094d0327f178d0caryclark#if DEBUG_LIMIT_WIND_SUM
15165f553182ab7069378ef863d30094d0327f178d0caryclark    SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM);
15265f553182ab7069378ef863d30094d0327f178d0caryclark    SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM);
15365f553182ab7069378ef863d30094d0327f178d0caryclark#endif
154ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (this->operand()) {
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkTSwap<int>(sumMiWinding, sumSuWinding);
15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
157ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding);
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
160ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end,
161ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkPathOp op, int* sumMiWinding, int* sumSuWinding) {
1624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
163ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    this->setUpWindings(start, end, sumMiWinding, sumSuWinding,
1644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool miFrom;
16607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool miTo;
16707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool suFrom;
16807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool suTo;
16907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
1704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miFrom = (oppMaxWinding & xorMiMask) != 0;
1714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miTo = (oppSumWinding & xorMiMask) != 0;
1724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suFrom = (maxWinding & xorSuMask) != 0;
1734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suTo = (sumWinding & xorSuMask) != 0;
17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
1754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miFrom = (maxWinding & xorMiMask) != 0;
1764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miTo = (sumWinding & xorMiMask) != 0;
1774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suFrom = (oppMaxWinding & xorSuMask) != 0;
1784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suTo = (oppSumWinding & xorSuMask) != 0;
17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
18007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
18107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ACTIVE_OP
182dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n",
183ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            __FUNCTION__, debugID(), start->t(), end->t(),
184570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
18507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return result;
18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
189ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end) {
190ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumWinding = updateWinding(end, start);
191ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return activeWinding(start, end, &sumWinding);
19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
194ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding) {
1954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int maxWinding;
196ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    setUpWinding(start, end, &maxWinding, sumWinding);
1974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool from = maxWinding != 0;
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool to = *sumWinding  != 0;
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool result = gUnaryActiveEdge[from][to];
20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return result;
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
203ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end,
204ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkPathWriter* path, bool active) const {
20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPoint edge[4];
20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint* ePtr;
207ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if ((start == &fHead && end == &fTail) || (start == &fTail && end == &fHead)) {
20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        ePtr = fPts;
20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZE? if not active, skip remainder and return xyAtT(end)
21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        subDivide(start, end, edge);
21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        ePtr = edge;
21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (active) {
215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bool reverse = ePtr == fPts && start != &fHead;
21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (reverse) {
217277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com            path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]);
21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            switch (fVerb) {
21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kLine_Verb:
22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->deferredLine(ePtr[0]);
22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kQuad_Verb:
22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->quadTo(ePtr[1], ePtr[0]);
22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kCubic_Verb:
22607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->cubicTo(ePtr[2], ePtr[1], ePtr[0]);
22707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
22807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                default:
22907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    SkASSERT(0);
23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com       } else {
23207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            path->deferredMoveLine(ePtr[0]);
23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            switch (fVerb) {
23407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kLine_Verb:
23507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->deferredLine(ePtr[1]);
23607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
23707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kQuad_Verb:
23807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->quadTo(ePtr[1], ePtr[2]);
23907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                case SkPath::kCubic_Verb:
24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    path->cubicTo(ePtr[1], ePtr[2], ePtr[3]);
24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    break;
24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                default:
24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    SkASSERT(0);
24507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
250ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* allocator) {
251ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* existing = NULL;
252ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* test = &fHead;
253ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double testT;
2544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
255ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if ((testT = test->ptT()->fT) >= t) {
256ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (testT == t) {
257ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                existing = test;
258ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
259ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            break;
260ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
261ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((test = test->upCast()->next()));
262ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpPtT* result;
263ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (existing && existing->contains(opp)) {
264ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        result = existing->ptT();
265ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } else {
266ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        result = this->addT(t, SkOpSegment::kNoAlias, allocator);
26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
268ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(result);
269ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return result;
27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
272ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** anglePtr,
273ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkChunkAlloc* allocator) {
274ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* startSpan = fTail.prev();
275ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(startSpan);
276ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
277ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *anglePtr = angle;
278ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    angle->set(&fTail, startSpan);
279ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fTail.setFromAngle(angle);
280ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = NULL;  // these initializations silence a release build warning
281ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* oStartSpan = NULL;
282ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* oEndSpan = NULL;
283ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpPtT* ptT = fTail.ptT(), * startPtT = ptT;
284ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((ptT = ptT->next()) != startPtT) {
285ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        other = ptT->segment();
286ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oStartSpan = ptT->span()->upCastable();
287ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (oStartSpan && oStartSpan->windValue()) {
288ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            oEndSpan = oStartSpan->next();
2894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            break;
2904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
291ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oEndSpan = ptT->span();
292ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oStartSpan = oEndSpan->prev();
293ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (oStartSpan && oStartSpan->windValue()) {
2944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            break;
2954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
296ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
297ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
298ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    oAngle->set(oStartSpan, oEndSpan);
299ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    oStartSpan->setToAngle(oAngle);
3004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    *otherPtr = other;
301ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return oAngle;
3024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
3034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
304ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngles(int step, SkChunkAlloc* allocator) {
3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpSegment* other;
306dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* angle, * otherAngle;
3074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (step > 0) {
308ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        otherAngle = addSingletonAngleUp(&other, &angle, allocator);
3094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
310ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        otherAngle = addSingletonAngleDown(&other, &angle, allocator);
3114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
312dac1d17027dcaa5596885a9f333979418b35001ccaryclark    angle->insert(otherAngle);
313dac1d17027dcaa5596885a9f333979418b35001ccaryclark    return angle;
3144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
3154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
316ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr,
317ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkChunkAlloc* allocator) {
318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* endSpan = fHead.next();
319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endSpan);
320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *anglePtr = angle;
322ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    angle->set(&fHead, endSpan);
323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fHead.setToAngle(angle);
324ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = NULL;  // these initializations silence a release build warning
325ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* oStartSpan = NULL;
326ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* oEndSpan = NULL;
327ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpPtT* ptT = fHead.ptT(), * startPtT = ptT;
328ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((ptT = ptT->next()) != startPtT) {
329ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        other = ptT->segment();
330ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oEndSpan = ptT->span();
331ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oStartSpan = oEndSpan->prev();
332ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (oStartSpan && oStartSpan->windValue()) {
333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            break;
334ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
335ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        oStartSpan = oEndSpan->upCastable();
336ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (oStartSpan && oStartSpan->windValue()) {
337ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            oEndSpan = oStartSpan->next();
338ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            break;
339ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
340ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
341ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
342ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    oAngle->set(oEndSpan, oStartSpan);
343ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    oEndSpan->setFromAngle(oAngle);
344ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *otherPtr = other;
345ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return oAngle;
3464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
3474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
348ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpPtT* SkOpSegment::addT(double t, AllowAlias allowAlias, SkChunkAlloc* allocator) {
349ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
350ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkPoint pt = this->ptAtT(t);
351ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* span = &fHead;
3524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
353ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpPtT* result = span->ptT();
354ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (t == result->fT) {
355ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            return result;
356ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
357ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (this->match(result, this, t, pt)) {
358ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            // see if any existing alias matches segment, pt, and t
359ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* loop = result->next();
360ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            bool duplicatePt = false;
361ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            while (loop != result) {
362ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                bool ptMatch = loop->fPt == pt;
363ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (loop->segment() == this && loop->fT == t && ptMatch) {
364ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    return result;
365ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                }
366ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                duplicatePt |= ptMatch;
367ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                loop = loop->next();
368ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
369ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (kNoAlias == allowAlias) {
370ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                return result;
371ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
372ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator);
373ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            alias->init(result->span(), t, pt, duplicatePt);
374ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            result->insert(alias);
375ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            result->span()->unaligned();
376ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            this->debugValidate();
377ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_ADD_T
378ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n",  __FUNCTION__, t,
379ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    alias->segment()->debugID(), alias->span()->debugID());
380ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
381ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            return alias;
382ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
383ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (t < result->fT) {
384ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSpan* prev = result->span()->prev();
385ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSpan* span = insert(prev, allocator);
386ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            span->init(this, prev, t, pt);
387ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            this->debugValidate();
388ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_ADD_T
389ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t,
390ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    span->segment()->debugID(), span->debugID());
391ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
392ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            return span->ptT();
393ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
394ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkASSERT(span != &fTail);
395ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((span = span->upCast()->next()));
396ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(0);
397ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return NULL;
3984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
3994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
400ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// choose a solitary t and pt value; remove aliases; align the opposite ends
401ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::align() {
402ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
403ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* span = &fHead;
404ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!span->aligned()) {
405ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        span->alignEnd(0, fPts[0]);
406ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
407ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((span = span->upCast()->next())) {
408ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (span == &fTail) {
40907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            break;
41007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
411ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        span->align();
41207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
413ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!span->aligned()) {
414ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]);
41507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
416ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
417ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
418ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
419ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::BetweenTs(const SkOpSpanBase* lesser, double testT,
420ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        const SkOpSpanBase* greater) {
421ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (lesser->t() > greater->t()) {
422ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkTSwap<const SkOpSpanBase*>(lesser, greater);
423dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
424ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return approximately_between(lesser->t(), testT, greater->t());
42565f553182ab7069378ef863d30094d0327f178d0caryclark}
42665f553182ab7069378ef863d30094d0327f178d0caryclark
427ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::calcAngles(SkChunkAlloc* allocator) {
428ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool activePrior = !fHead.isCanceled();
429ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (activePrior && !fHead.simple()) {
430ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        addStartSpan(allocator);
43107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
432ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* prior = &fHead;
433ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* spanBase = fHead.next();
434ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while (spanBase != &fTail) {
435ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (activePrior) {
436ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpAngle* priorAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
437ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            priorAngle->set(spanBase, prior);
438ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            spanBase->setFromAngle(priorAngle);
43907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
440ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpan* span = spanBase->upCast();
441ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bool active = !span->isCanceled();
442ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* next = span->next();
443ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (active) {
444ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
445ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            angle->set(span, next);
446ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            span->setToAngle(angle);
447ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
448ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        activePrior = active;
449ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        prior = span;
450ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        spanBase = next;
4514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
452ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (activePrior && !fTail.simple()) {
453ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        addEndSpan(allocator);
4544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
45565f553182ab7069378ef863d30094d0327f178d0caryclark}
45665f553182ab7069378ef863d30094d0327f178d0caryclark
457ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) {
458ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* base = &fHead;
459ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* span;
46065f553182ab7069378ef863d30094d0327f178d0caryclark    do {
461ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle* angle = base->fromAngle();
462ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (angle && angle->fCheckCoincidence) {
463ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            angle->checkNearCoincidence();
46465f553182ab7069378ef863d30094d0327f178d0caryclark        }
465ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (base->final()) {
466ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark             break;
46765f553182ab7069378ef863d30094d0327f178d0caryclark        }
468ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        span = base->upCast();
469ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        angle = span->toAngle();
470ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (angle && angle->fCheckCoincidence) {
471ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            angle->checkNearCoincidence();
47265f553182ab7069378ef863d30094d0327f178d0caryclark        }
473ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((base = span->next()));
47407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
47507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
476ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order
477ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swap) const {
478ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(fVerb != SkPath::kLine_Verb);
479ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkPoint edge[4];
480ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (fVerb == SkPath::kCubic_Verb) {
481ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double startT = start->t();
482ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double endT = end->t();
483ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bool flip = startT > endT;
484ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDCubic cubic;
485ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        cubic.set(fPts);
486ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double inflectionTs[2];
487ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int inflections = cubic.findInflections(inflectionTs);
488ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        for (int index = 0; index < inflections; ++index) {
489ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            double inflectionT = inflectionTs[index];
490ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (between(startT, inflectionT, endT)) {
491ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (flip) {
492ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (inflectionT != endT) {
493ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        startT = inflectionT;
494ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
495a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com                } else {
496ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (inflectionT != startT) {
497ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        endT = inflectionT;
498ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
499a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com                }
500dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
501dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
502ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDCubic part = cubic.subDivide(startT, endT);
503ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        for (int index = 0; index < 4; ++index) {
504ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            edge[index] = part[index].asSkPoint();
505ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
506ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } else {
507ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    subDivide(start, end, edge);
508dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
509ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool sumSet = false;
510ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int points = SkPathOpsVerbToPoints(fVerb);
511ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY);
512ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!sumSet) {
513ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        for (int idx = 0; idx < points; ++idx){
514ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY);
51507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
51607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
517ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (fVerb == SkPath::kCubic_Verb) {
518ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDCubic cubic;
519ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        cubic.set(edge);
520ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *swap = sum > 0 && !cubic.monotonicInY();
521ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } else {
522ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDQuad quad;
523ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        quad.set(edge);
524ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *swap = sum > 0 && !quad.monotonicInY();
52507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
526ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return sum <= 0;
52707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
52807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
529ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
530ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle::IncludeType includeType) {
531ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSegment* baseSegment = baseAngle->segment();
532ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
533ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumSuWinding;
534ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool binary = includeType >= SkOpAngle::kBinarySingle;
535ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (binary) {
536ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle);
537ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (baseSegment->operand()) {
538ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkTSwap<int>(sumMiWinding, sumSuWinding);
53919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark        }
540ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
541ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* nextSegment = nextAngle->segment();
542ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int maxWinding, sumWinding;
543ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last;
544ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (binary) {
545ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int oppMaxWinding, oppSumWinding;
546ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
547ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
548ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
549ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                nextAngle);
5504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
551ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
552ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                &maxWinding, &sumWinding);
553ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
5544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
555ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    nextAngle->setLastMarked(last);
5564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
5574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
558ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
559ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle::IncludeType includeType) {
560ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSegment* baseSegment = baseAngle->segment();
561ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumMiWinding = baseSegment->updateWinding(baseAngle);
562ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumSuWinding;
563ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool binary = includeType >= SkOpAngle::kBinarySingle;
564570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (binary) {
565ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        sumSuWinding = baseSegment->updateOppWinding(baseAngle);
566ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (baseSegment->operand()) {
567ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkTSwap<int>(sumMiWinding, sumSuWinding);
568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
5694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
570ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* nextSegment = nextAngle->segment();
571ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int maxWinding, sumWinding;
572ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last;
573ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (binary) {
574ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int oppMaxWinding, oppSumWinding;
575ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
576ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
578ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                nextAngle);
5794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
580ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
581ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                &maxWinding, &sumWinding);
582ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
583570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
584ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    nextAngle->setLastMarked(last);
5854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
5864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
587dac1d17027dcaa5596885a9f333979418b35001ccaryclark// at this point, the span is already ordered, or unorderable
588ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end,
589ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle::IncludeType includeType) {
5904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkASSERT(includeType != SkOpAngle::kUnaryXor);
591ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* firstAngle = this->spanToAngle(end, start);
59265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark    if (NULL == firstAngle || NULL == firstAngle->next()) {
5934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return SK_NaN32;
594570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
595570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    // if all angles have a computed winding,
596570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  or if no adjacent angles are orderable,
597570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  or if adjacent orderable angles have no computed winding,
598570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  there's nothing to do
599dac1d17027dcaa5596885a9f333979418b35001ccaryclark    // if two orderable angles are adjacent, and both are next to orderable angles,
600dac1d17027dcaa5596885a9f333979418b35001ccaryclark    //  and one has winding computed, transfer to the other
6014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* baseAngle = NULL;
602570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool tryReverse = false;
603570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    // look for counterclockwise transfers
604dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* angle = firstAngle->previous();
605dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* next = angle->next();
606dac1d17027dcaa5596885a9f333979418b35001ccaryclark    firstAngle = next;
60707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
608dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkOpAngle* prior = angle;
609dac1d17027dcaa5596885a9f333979418b35001ccaryclark        angle = next;
610dac1d17027dcaa5596885a9f333979418b35001ccaryclark        next = angle->next();
611dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkASSERT(prior->next() == angle);
612dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkASSERT(angle->next() == next);
613dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
614dac1d17027dcaa5596885a9f333979418b35001ccaryclark            baseAngle = NULL;
6154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
6164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
617ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int testWinding = angle->starter()->windSum();
618dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (SK_MinS32 != testWinding) {
619dac1d17027dcaa5596885a9f333979418b35001ccaryclark            baseAngle = angle;
6204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            tryReverse = true;
6214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
6224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
6234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (baseAngle) {
6244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            ComputeOneSum(baseAngle, angle, includeType);
625ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : NULL;
6264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
627dac1d17027dcaa5596885a9f333979418b35001ccaryclark    } while (next != firstAngle);
628ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) {
6294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        firstAngle = baseAngle;
6304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        tryReverse = true;
6314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
6324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (tryReverse) {
6334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        baseAngle = NULL;
634dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkOpAngle* prior = firstAngle;
635570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        do {
636dac1d17027dcaa5596885a9f333979418b35001ccaryclark            angle = prior;
637dac1d17027dcaa5596885a9f333979418b35001ccaryclark            prior = angle->previous();
638dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(prior->next() == angle);
639dac1d17027dcaa5596885a9f333979418b35001ccaryclark            next = angle->next();
640dac1d17027dcaa5596885a9f333979418b35001ccaryclark            if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
641dac1d17027dcaa5596885a9f333979418b35001ccaryclark                baseAngle = NULL;
642dac1d17027dcaa5596885a9f333979418b35001ccaryclark                continue;
643dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
644ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            int testWinding = angle->starter()->windSum();
6454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (SK_MinS32 != testWinding) {
6464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                baseAngle = angle;
647570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                continue;
64807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
649570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            if (baseAngle) {
6504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                ComputeOneSumReverse(baseAngle, angle, includeType);
651ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : NULL;
652570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
653dac1d17027dcaa5596885a9f333979418b35001ccaryclark        } while (prior != firstAngle);
654570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
655ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return start->starter(end)->windSum();
65607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
65707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
658ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpan* SkOpSegment::crossedSpanY(const SkPoint& basePt, double mid, bool opp, bool current,
659ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkScalar* bestY, double* hitT, bool* hitSomething, bool* vertical) {
66007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar bottom = fBounds.fBottom;
661ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *vertical = false;
66207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (bottom <= *bestY) {
663ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
66407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
66507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar top = fBounds.fTop;
66607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (top >= basePt.fY) {
667ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
66807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
66907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fBounds.fLeft > basePt.fX) {
670ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
67107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
67207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fBounds.fRight < basePt.fX) {
673ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
67407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
67507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fBounds.fLeft == fBounds.fRight) {
676ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        // if vertical, and directly above test point, wait for another one
677ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *vertical = AlmostEqualUlps(basePt.fX, fBounds.fLeft);
678ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
6794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
680ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // intersect ray starting at basePt with edge
681ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkIntersections intersections;
682ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // OPTIMIZE: use specialty function that intersects ray with curve,
683ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // returning t values only for curve (we don't care about t on ray)
684ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    intersections.allowNear(false);
685ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)])
686ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            (fPts, top, bottom, basePt.fX, false);
687ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (pts == 0 || (current && pts == 1)) {
688ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
6894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
690ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (current) {
691ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkASSERT(pts > 1);
692ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int closestIdx = 0;
693ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double closest = fabs(intersections[0][0] - mid);
694ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        for (int idx = 1; idx < pts; ++idx) {
695ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            double test = fabs(intersections[0][idx] - mid);
696ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (closest > test) {
697ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                closestIdx = idx;
698ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                closest = test;
6994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
7004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
701ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        intersections.quickRemoveOne(closestIdx, --pts);
7024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
703ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double bestT = -1;
704ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    for (int index = 0; index < pts; ++index) {
705ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double foundT = intersections[0][index];
706ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (approximately_less_than_zero(foundT)
707ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    || approximately_greater_than_one(foundT)) {
708570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            continue;
709570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
710ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkScalar testY = (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fY;
711ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (approximately_negative(testY - *bestY)
712ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                || approximately_negative(basePt.fY - testY)) {
713570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            continue;
714570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
715ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (pts > 1 && fVerb == SkPath::kLine_Verb) {
716ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            *vertical = true;
717ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            return NULL;  // if the intersection is edge on, wait for another one
718ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
719ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (fVerb > SkPath::kLine_Verb) {
720ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fX;
721ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (approximately_zero(dx)) {
722ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                *vertical = true;
723ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                return NULL;  // hit vertical, wait for another one
724570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
725570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
726ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *bestY = testY;
727ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bestT = foundT;
728570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
729ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (bestT < 0) {
730ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
731570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
732ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(bestT >= 0);
733ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(bestT < 1);
734ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* testTSpanBase = &this->fHead;
735ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* nextTSpan;
736ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double endT = 0;
737ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
738ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        nextTSpan = testTSpanBase->upCast()->next();
739ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        endT = nextTSpan->t();
740ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (endT >= bestT) {
741ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            break;
7424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
743ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        testTSpanBase = nextTSpan;
744ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while (testTSpanBase);
745ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* bestTSpan = NULL;
746ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* testTSpan = testTSpanBase->upCast();
747ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!testTSpan->isCanceled()) {
748ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *hitT = bestT;
749ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bestTSpan = testTSpan;
750ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *hitSomething = true;
751570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
752ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return bestTSpan;
75307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
75407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
755ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::detach(const SkOpSpan* span) {
756ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (span->done()) {
757ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        --this->fDoneCount;
758dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
759ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    --this->fCount;
760dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
761dac1d17027dcaa5596885a9f333979418b35001ccaryclark
762ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkdouble SkOpSegment::distSq(double t, SkOpAngle* oppAngle) {
763ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDPoint testPt = this->dPtAtT(t);
764ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDLine testPerp = {{ testPt, testPt }};
765ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDVector slope = this->dSlopeAtT(t);
766ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    testPerp[1].fX += slope.fY;
767ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    testPerp[1].fY -= slope.fX;
768ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkIntersections i;
769ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* oppSegment = oppAngle->segment();
770ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppPtCount = SkPathOpsVerbToPoints(oppSegment->verb());
771ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (*CurveIntersectRay[oppPtCount])(oppSegment->pts(), testPerp, &i);
772ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double closestDistSq = SK_ScalarInfinity;
773ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    for (int index = 0; index < i.used(); ++index) {
774ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) {
775ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            continue;
776a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        }
777ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        double testDistSq = testPt.distanceSquared(i.pt(index));
778ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (closestDistSq > testDistSq) {
779ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            closestDistSq = testDistSq;
780a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        }
781ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
782ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return closestDistSq;
7834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
7844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
78507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
78607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The M and S variable name parts stand for the operators.
78707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com   Mi stands for Minuend (see wiki subtraction, analogous to difference)
78807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com   Su stands for Subtrahend
78907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The Opp variable name part designates that the value is for the Opposite operator.
79007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Opposite values result from combining coincident spans.
79107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
792ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart,
793ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) {
794ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* start = *nextStart;
795ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* end = *nextEnd;
796ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != end);
797ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
798ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
799ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (other) {
80007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // mark the smaller of startIndex, endIndex done, and all adjacent
80107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // spans with the same T value (but not 'other' spans)
80207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
80307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
80407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
805ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpan* startSpan = start->starter(end);
806ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (startSpan->done()) {
807cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return NULL;
808cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
809ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(startSpan);
810ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
81107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
81207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
813ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
814ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear == end);  // is this ever not end?
815ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear);
816ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != endNear);
817ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
8184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // more than one viable candidate -- measure angles to find best
819ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp);
820570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool sortable = calcWinding != SK_NaN32;
8214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (!sortable) {
8227eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        *unsortable = true;
823ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
8247eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        return NULL;
8257eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    }
826ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
8274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (angle->unorderable()) {
82807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *unsortable = true;
829ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
83007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return NULL;
83107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
8334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
8344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
83507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
836ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumMiWinding = updateWinding(end, start);
8378cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    if (sumMiWinding == SK_MinS32) {
8388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        *unsortable = true;
839ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
8408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        return NULL;
8418cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    }
842ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumSuWinding = updateOppWinding(end, start);
84307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
84407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkTSwap<int>(sumMiWinding, sumSuWinding);
84507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
84707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkOpAngle* foundAngle = NULL;
84807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
84907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // iterate through the angle, and compute everyone's winding
85007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
85107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
85207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
85307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
85407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
85607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (activeAngle) {
85707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++activeCount;
85807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (!foundAngle || (foundDone && activeCount & 1)) {
85907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundAngle = nextAngle;
860570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                foundDone = nextSegment->done(nextAngle);
86107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
86207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
86307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (nextSegment->done()) {
86407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            continue;
86507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
866570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (!activeAngle) {
867ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end());
868570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
869ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* last = nextAngle->lastMarked();
87007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (last) {
8714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
87207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            *chase->append() = last;
87307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
874ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
875ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    last->segment()->debugID(), last->debugID());
876ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!last->final()) {
877ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkDebugf(" windSum=%d", last->upCast()->windSum());
878ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
879ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("\n");
88007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
88107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
8824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while ((nextAngle = nextAngle->next()) != angle);
883ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    start->segment()->markDone(start->starter(end));
88407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
88507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return NULL;
88607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
88707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
88807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
88907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
89007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
89107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
89207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
89307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
89407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
89507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
89607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
897ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpanBase*>* chase,
898ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable) {
899ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* start = *nextStart;
900ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* end = *nextEnd;
901ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != end);
902ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
903ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
904ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (other) {
90507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // mark the smaller of startIndex, endIndex done, and all adjacent
90607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // spans with the same T value (but not 'other' spans)
90707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
90807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
90907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
910ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpan* startSpan = start->starter(end);
911ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (startSpan->done()) {
912570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            return NULL;
913570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
914ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(startSpan);
915ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
91607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
91707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
918ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
919ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear == end);  // is this ever not end?
920ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear);
921ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != endNear);
922ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
9234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // more than one viable candidate -- measure angles to find best
924ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding);
925570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool sortable = calcWinding != SK_NaN32;
92607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!sortable) {
92707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *unsortable = true;
928ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
929ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
930ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
931ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
932ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (angle->unorderable()) {
933ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *unsortable = true;
934ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
93507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return NULL;
93607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
9384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
9394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
94007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
941ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int sumWinding = updateWinding(end, start);
9424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
94307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkOpAngle* foundAngle = NULL;
94407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
945ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // iterate through the angle, and compute everyone's winding
94607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
94707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
94807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
94907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
95007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
9514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                &sumWinding);
95207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (activeAngle) {
95307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++activeCount;
95407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (!foundAngle || (foundDone && activeCount & 1)) {
95507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundAngle = nextAngle;
95607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundDone = nextSegment->done(nextAngle);
95707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
95807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
95907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (nextSegment->done()) {
96007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            continue;
96107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
962570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (!activeAngle) {
963ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end());
964570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
965ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* last = nextAngle->lastMarked();
96607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (last) {
9674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
96807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            *chase->append() = last;
96907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
970ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
971ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    last->segment()->debugID(), last->debugID());
972ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!last->final()) {
973ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkDebugf(" windSum=%d", last->upCast()->windSum());
974ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
975ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("\n");
97607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
97707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
9784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while ((nextAngle = nextAngle->next()) != angle);
979ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    start->segment()->markDone(start->starter(end));
98007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
98107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return NULL;
98207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
98307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
98407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
98507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
98607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
98707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
98807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
98907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
99007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
99107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
99207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
993ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd,
994ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bool* unsortable) {
995ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* start = *nextStart;
996ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* end = *nextEnd;
997ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != end);
998ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
999ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
1000ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (other) {
1001ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // mark the smaller of startIndex, endIndex done, and all adjacent
1002ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // spans with the same T value (but not 'other' spans)
100307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
100407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
100507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
1006ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpan* startSpan = start->starter(end);
1007ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (startSpan->done()) {
100807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            return NULL;
100907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1010ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(startSpan);
1011ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
101207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
101307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1014ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \
1015ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            : (*nextStart)->prev());
1016ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear == end);  // is this ever not end?
1017ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endNear);
1018ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(start != endNear);
1019ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
1020ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
1021ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (angle->unorderable()) {
1022ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *unsortable = true;
1023ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markDone(start->starter(end));
1024ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return NULL;
1025ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
10264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
10274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
10284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
1029570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
10304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
103107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkOpAngle* foundAngle = NULL;
103207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
1033ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // iterate through the angle, and compute everyone's winding
103407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
103507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
103607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
103707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
103807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        ++activeCount;
103907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (!foundAngle || (foundDone && activeCount & 1)) {
104007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            foundAngle = nextAngle;
10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (!(foundDone = nextSegment->done(nextAngle))) {
10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                break;
10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
104407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
10454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        nextAngle = nextAngle->next();
10464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while (nextAngle != angle);
1047ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    start->segment()->markDone(start->starter(end));
104807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
104907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return NULL;
105007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
105107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
105207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
105307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
105407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
105507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
105607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
105707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
105807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
105907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
106007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1061ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr,
1062ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        bool* unsortable, SkChunkAlloc* allocator) {
106307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // iterate through T intersections and return topmost
106407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // topmost tangent from y-min to first pt is closer to horizontal
106507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(!done());
1066ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* firstT = NULL;
1067ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (void) this->activeLeftTop(&firstT);
1068ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!firstT) {
10698cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        *unsortable = !firstPass;
1070ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        firstT = &fHead;
1071ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        while (firstT->upCast()->done()) {
1072ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            firstT = firstT->upCast()->next();
107307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1074ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *startPtr = firstT;
1075ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *endPtr = firstT->upCast()->next();
107607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return this;
107707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
107807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // sort the edges to find the leftmost
107907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int step = 1;
1080ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* end;
1081ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (firstT->final() || firstT->upCast()->done()) {
108207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        step = -1;
1083ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        end = firstT->prev();
1084ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkASSERT(end);
1085ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } else {
1086ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        end = firstT->upCast()->next();
108707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
108807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // if the topmost T is not on end, or is three-way or more, find left
108907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // look for left-ness from tLeft to firstT (matching y of other)
1090ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(firstT != end);
10914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* markAngle = spanToAngle(firstT, end);
10924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (!markAngle) {
1093ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        markAngle = addSingletonAngles(step, allocator);
10944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
10954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    markAngle->markStops();
1096e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark    const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle
1097e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark            : markAngle->findFirst();
10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (!baseAngle) {
10994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return NULL;  // nothing to do
1100570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
110107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar top = SK_ScalarMax;
11024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* firstAngle = NULL;
11034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* angle = baseAngle;
11044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
11054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (!angle->unorderable()) {
1106ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const SkOpSegment* next = angle->segment();
11074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkPathOpsBounds bounds;
11084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            next->subDivideBounds(angle->end(), angle->start(), &bounds);
110965f553182ab7069378ef863d30094d0327f178d0caryclark            bool nearSame = AlmostEqualUlps(top, bounds.top());
111065f553182ab7069378ef863d30094d0327f178d0caryclark            bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->sectorStart();
111165f553182ab7069378ef863d30094d0327f178d0caryclark            bool lesserSector = top > bounds.fTop;
111265f553182ab7069378ef863d30094d0327f178d0caryclark            if (lesserSector && (!nearSame || lowerSector)) {
11134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                top = bounds.fTop;
11144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                firstAngle = angle;
11154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
111607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
11174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        angle = angle->next();
11184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while (angle != baseAngle);
111965f553182ab7069378ef863d30094d0327f178d0caryclark    if (!firstAngle) {
112065f553182ab7069378ef863d30094d0327f178d0caryclark        return NULL;  // if all are unorderable, give up
112165f553182ab7069378ef863d30094d0327f178d0caryclark    }
11224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
11234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
11244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    firstAngle->debugLoop();
112507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
112607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // skip edges that have already been processed
11274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle = firstAngle;
11288cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    SkOpSegment* leftSegment = NULL;
11298cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    bool looped = false;
113007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
11318cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        *unsortable = angle->unorderable();
11328cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        if (firstPass || !*unsortable) {
11338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org            leftSegment = angle->segment();
1134ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            *startPtr = angle->end();
1135ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            *endPtr = angle->start();
1136ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const SkOpSpan* firstSpan = (*startPtr)->starter(*endPtr);
1137ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!firstSpan->done()) {
11388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                break;
11398cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org            }
11408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        }
11414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        angle = angle->next();
11428cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        looped = true;
11438cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    } while (angle != firstAngle);
11448cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    if (angle == firstAngle && looped) {
11458cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        return NULL;
11468cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    }
114707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (leftSegment->verb() >= SkPath::kQuad_Verb) {
1148ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* start = *startPtr;
1149ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* end = *endPtr;
1150e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark        bool swap;
1151ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (!leftSegment->clockwise(start, end, &swap)) {
115207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    #if DEBUG_SWAP_TOP
1153ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s swap=%d inflections=%d monotonic=%d\n",
11548cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                    __FUNCTION__,
1155ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    swap, leftSegment->debugInflections(start, end),
1156ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    leftSegment->monotonicInY(start, end));
115707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    #endif
115807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (swap) {
115907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not the first
116007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // sorted but merely the first not already processed (i.e., not done)
1161ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkTSwap(*startPtr, *endPtr);
116207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
116307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
116407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
116507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return leftSegment;
116607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
116707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1168ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpGlobalState* SkOpSegment::globalState() const {
1169ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return contour()->globalState();
117065f553182ab7069378ef863d30094d0327f178d0caryclark}
117165f553182ab7069378ef863d30094d0327f178d0caryclark
1172ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::init(SkPoint pts[], SkOpContour* contour, SkPath::Verb verb) {
1173ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fContour = contour;
1174ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fNext = NULL;
117507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPts = pts;
117607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fVerb = verb;
1177ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fCount = 0;
1178ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fDoneCount = 0;
1179ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    fVisited = false;
1180ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* zeroSpan = &fHead;
1181ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    zeroSpan->init(this, NULL, 0, fPts[0]);
1182ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* oneSpan = &fTail;
1183ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    zeroSpan->setNext(oneSpan);
1184ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]);
1185ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    PATH_OPS_DEBUG_CODE(fID = globalState()->nextSegmentID());
1186ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1187ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1188ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::initWinding(SkOpSpanBase* start, SkOpSpanBase* end,
1189ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle::IncludeType angleIncludeType) {
1190ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int local = SkOpSegment::SpanSign(start, end);
119165f553182ab7069378ef863d30094d0327f178d0caryclark    SkDEBUGCODE(bool success);
11924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (angleIncludeType == SkOpAngle::kBinarySingle) {
1193ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int oppLocal = SkOpSegment::OppSign(start, end);
119465f553182ab7069378ef863d30094d0327f178d0caryclark        SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, oppLocal, NULL);
119507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZATION: the reverse mark and chase could skip the first marking
119665f553182ab7069378ef863d30094d0327f178d0caryclark        SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, oppLocal, NULL);
11974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
119865f553182ab7069378ef863d30094d0327f178d0caryclark        SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, NULL);
11994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // OPTIMIZATION: the reverse mark and chase could skip the first marking
120065f553182ab7069378ef863d30094d0327f178d0caryclark        SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, NULL);
12014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
120265f553182ab7069378ef863d30094d0327f178d0caryclark    SkASSERT(success);
120307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
120407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
120507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
120607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comwhen we start with a vertical intersect, we try to use the dx to determine if the edge is to
120707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe left or the right of vertical. This determines if we need to add the span's
120807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comsign or not. However, this isn't enough.
120907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf the supplied sign (winding) is zero, then we didn't hit another vertical span, so dx is needed.
121007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf there was a winding, then it may or may not need adjusting. If the span the winding was borrowed
121107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comfrom has the same x direction as this span, the winding should change. If the dx is opposite, then
121207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe same winding is shared by both.
121307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com*/
1214ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::initWinding(SkOpSpanBase* start, SkOpSpanBase* end, double tHit,
1215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int winding, SkScalar hitDx, int oppWind, SkScalar hitOppDx) {
1216ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(this == start->segment());
121707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(hitDx || !winding);
1218277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
1219ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark//    SkASSERT(dx);
1220ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int windVal = start->starter(end)->windValue();
122107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T
1222dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, debugID(), winding,
122307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
122407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
12254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int sideWind = winding + (dx < 0 ? windVal : -windVal);
12264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (abs(winding) < abs(sideWind)) {
12274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        winding = sideWind;
122807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1229ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDEBUGCODE(int oppLocal = SkOpSegment::OppSign(start, end));
123007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(hitOppDx || !oppWind || !oppLocal);
1231ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppWindVal = start->starter(end)->oppValue();
123207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!oppWind) {
123307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        oppWind = dx < 0 ? oppWindVal : -oppWindVal;
123407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else if (hitOppDx * dx >= 0) {
123507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
123607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (abs(oppWind) < abs(oppSideWind)) {
123707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            oppWind = oppSideWind;
123807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
123907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1240dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING_AT_T
1241dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind);
1242dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif
124365f553182ab7069378ef863d30094d0327f178d0caryclark    // if this fails to mark (because the edges are too small) inform caller to try again
124465f553182ab7069378ef863d30094d0327f178d0caryclark    bool success = markAndChaseWinding(start, end, winding, oppWind, NULL);
12457eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    // OPTIMIZATION: the reverse mark and chase could skip the first marking
124665f553182ab7069378ef863d30094d0327f178d0caryclark    success |= markAndChaseWinding(end, start, winding, oppWind, NULL);
124765f553182ab7069378ef863d30094d0327f178d0caryclark    return success;
124807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
124907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1250ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::isClose(double t, const SkOpSegment* opp) const {
1251ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDPoint cPt = this->dPtAtT(t);
1252ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int pts = SkPathOpsVerbToPoints(this->verb());
1253ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDVector dxdy = (*CurveDSlopeAtT[pts])(this->pts(), t);
1254ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
1255ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkIntersections i;
1256ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppPts = SkPathOpsVerbToPoints(opp->verb());
1257ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (*CurveIntersectRay[oppPts])(opp->pts(), perp, &i);
1258ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int used = i.used();
1259ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    for (int index = 0; index < used; ++index) {
1260ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (cPt.roughlyEqual(i.pt(index))) {
1261866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org            return true;
1262866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org        }
1263ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
1264a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    return false;
1265a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com}
1266a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com
1267ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::isXor() const {
1268ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return fContour->isXor();
126907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
127007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1271ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end) {
1272ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
1273ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* minSpan = start->starter(end);
1274ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    markDone(minSpan);
1275ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last = NULL;
127607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* other = this;
1277ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((other = other->nextChase(&start, &step, &minSpan, &last))) {
127807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (other->done()) {
1279dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
1280dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
128107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1282ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        other->markDone(minSpan);
128307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
128407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
128507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
128607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1287ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding,
1288ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** lastPtr) {
1289ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* spanStart = start->starter(end);
1290ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
1291ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool success = markWinding(spanStart, winding);
1292ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last = NULL;
12934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpSegment* other = this;
1294ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
1295ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (spanStart->windSum() != SK_MinS32) {
1296ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkASSERT(spanStart->windSum() == winding);
1297dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
1298dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
12994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1300ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        (void) other->markWinding(spanStart, winding);
13016f726addf3178b01949bb389ef83cf14a1d7b6b2caryclark    }
130265f553182ab7069378ef863d30094d0327f178d0caryclark    if (lastPtr) {
130365f553182ab7069378ef863d30094d0327f178d0caryclark        *lastPtr = last;
130465f553182ab7069378ef863d30094d0327f178d0caryclark    }
130565f553182ab7069378ef863d30094d0327f178d0caryclark    return success;
13064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
13074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
1308ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end,
1309ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int winding, int oppWinding, SkOpSpanBase** lastPtr) {
1310ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* spanStart = start->starter(end);
1311ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int step = start->step(end);
1312ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    bool success = markWinding(spanStart, winding, oppWinding);
1313ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last = NULL;
131407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* other = this;
1315ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
1316ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (spanStart->windSum() != SK_MinS32) {
1317ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (this->operand() == other->operand()) {
1318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkASSERT(spanStart->windSum() == winding);
1319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (spanStart->oppSum() != oppWinding) {
1320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    this->globalState()->setWindingFailed();
1321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    return false;
1322dac1d17027dcaa5596885a9f333979418b35001ccaryclark                }
1323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            } else {
1324ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkASSERT(spanStart->windSum() == oppWinding);
1325ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkASSERT(spanStart->oppSum() == winding);
1326dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
1327dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
1328dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
1329dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
1330ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (this->operand() == other->operand()) {
1331ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            (void) other->markWinding(spanStart, winding, oppWinding);
1332dac1d17027dcaa5596885a9f333979418b35001ccaryclark        } else {
1333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            (void) other->markWinding(spanStart, oppWinding, winding);
133407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
133507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
133665f553182ab7069378ef863d30094d0327f178d0caryclark    if (lastPtr) {
133765f553182ab7069378ef863d30094d0327f178d0caryclark        *lastPtr = last;
133865f553182ab7069378ef863d30094d0327f178d0caryclark    }
133965f553182ab7069378ef863d30094d0327f178d0caryclark    return success;
134007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
134107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1342ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) {
134307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(angle->segment() == this);
134407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (UseInnerWinding(maxWinding, sumWinding)) {
134507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        maxWinding = sumWinding;
134607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1347ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last;
1348ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, &last);
1349570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING
1350570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (last) {
1351ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDebugf("%s last seg=%d span=%d", __FUNCTION__,
1352ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                last->segment()->debugID(), last->debugID());
1353ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (!last->final()) {
1354ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf(" windSum=");
1355ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkPathOpsDebug::WindingPrintf(last->upCast()->windSum());
1356ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
1357ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDebugf("\n");
1358570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
1359570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
136007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
136107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
136207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1363ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding,
1364ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                   int oppSumWinding, const SkOpAngle* angle) {
136507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(angle->segment() == this);
136607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (UseInnerWinding(maxWinding, sumWinding)) {
136707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        maxWinding = sumWinding;
136807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
136907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) {
137007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        oppMaxWinding = oppSumWinding;
137107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1372ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* last = NULL;
137365f553182ab7069378ef863d30094d0327f178d0caryclark    // caller doesn't require that this marks anything
1374ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, &last);
1375570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING
1376570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (last) {
1377ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDebugf("%s last segment=%d span=%d", __FUNCTION__,
1378ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                last->segment()->debugID(), last->debugID());
1379ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (!last->final()) {
1380ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf(" windSum=");
1381ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkPathOpsDebug::WindingPrintf(last->upCast()->windSum());
1382ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
1383ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDebugf(" \n");
1384570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
1385570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
138607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
138707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
138807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1389ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::markDone(SkOpSpan* span) {
1390ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(this == span->segment());
1391ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (span->done()) {
139207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
139307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1394ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_MARK_DONE
1395ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum());
1396ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
1397ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    span->setDone(true);
1398ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    ++fDoneCount;
1399ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
140007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
140107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1402ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding) {
1403ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(this == span->segment());
1404ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(winding);
1405ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (span->done()) {
140665f553182ab7069378ef863d30094d0327f178d0caryclark        return false;
140707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
140807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE
1409ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugShowNewWinding(__FUNCTION__, span, winding);
14108cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif
1411ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    span->setWindSum(winding);
1412ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
141365f553182ab7069378ef863d30094d0327f178d0caryclark    return true;
141407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
141507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1416ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding, int oppWinding) {
1417ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(this == span->segment());
1418ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(winding || oppWinding);
1419ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (span->done()) {
142065f553182ab7069378ef863d30094d0327f178d0caryclark        return false;
142107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
142207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE
1423ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugShowNewWinding(__FUNCTION__, span, winding, oppWinding);
14248cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif
1425ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    span->setWindSum(winding);
1426ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    span->setOppSum(oppWinding);
14274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    debugValidate();
142865f553182ab7069378ef863d30094d0327f178d0caryclark    return true;
142907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
143007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1431ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::match(const SkOpPtT* base, const SkOpSegment* testParent, double testT,
1432ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        const SkPoint& testPt) const {
1433ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSegment* baseParent = base->segment();
1434ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (this == baseParent && this == testParent && precisely_equal(base->fT, testT)) {
1435ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return true;
143607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1437ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) {
1438ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return false;
1439e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark    }
1440ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return !ptsDisjoint(base->fT, base->fPt, testT, testPt);
1441ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1442ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1443ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) {
1444ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (last) {
1445ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        *last = endSpan;
144607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1447ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return NULL;
144807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
144907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1450ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
14518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    SkASSERT(fVerb != SkPath::kLine_Verb);
145207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fVerb == SkPath::kQuad_Verb) {
1453ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDQuad dst = SkDQuad::SubDivide(fPts, start->t(), end->t());
145407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return dst.monotonicInY();
145507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
145607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(fVerb == SkPath::kCubic_Verb);
1457ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t());
145807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return dst.monotonicInY();
145907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
146007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1461ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start,
1462ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** end) {
1463ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    while (span->final() || span->upCast()->done()) {
1464ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (span->final()) {
146507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            return false;
146607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1467ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        span = span->upCast()->next();
146807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1469ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *start = span;
1470ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *end = span->upCast()->next();
147107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return true;
147207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
147307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1474ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr,
1475ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase** last) const {
1476ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* origStart = *startPtr;
1477dac1d17027dcaa5596885a9f333979418b35001ccaryclark    int step = *stepPtr;
1478ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev();
1479ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(endSpan);
1480ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle();
1481ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* foundSpan;
1482ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* otherEnd;
1483dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpSegment* other;
1484dac1d17027dcaa5596885a9f333979418b35001ccaryclark    if (angle == NULL) {
1485ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (endSpan->t() != 0 && endSpan->t() != 1) {
1486dac1d17027dcaa5596885a9f333979418b35001ccaryclark            return NULL;
1487dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
1488ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpPtT* otherPtT = endSpan->ptT()->next();
1489ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        other = otherPtT->segment();
1490ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        foundSpan = otherPtT->span();
1491ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        otherEnd = step > 0 ? foundSpan->upCast()->next() : foundSpan->prev();
1492dac1d17027dcaa5596885a9f333979418b35001ccaryclark    } else {
1493dac1d17027dcaa5596885a9f333979418b35001ccaryclark        int loopCount = angle->loopCount();
1494dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (loopCount > 2) {
1495ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            return set_last(last, endSpan);
1496dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
1497dac1d17027dcaa5596885a9f333979418b35001ccaryclark        const SkOpAngle* next = angle->next();
149865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark        if (NULL == next) {
149965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark            return NULL;
150065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark        }
1501dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING
1502ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (angle->sign() != next->sign() && !angle->segment()->contour()->isXor()
1503ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                && !next->segment()->contour()->isXor()) {
1504dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkDebugf("%s mismatched signs\n", __FUNCTION__);
1505dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
1506ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
1507dac1d17027dcaa5596885a9f333979418b35001ccaryclark        other = next->segment();
1508ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        foundSpan = endSpan = next->start();
1509dac1d17027dcaa5596885a9f333979418b35001ccaryclark        otherEnd = next->end();
1510570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
1511ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int foundStep = foundSpan->step(otherEnd);
1512dac1d17027dcaa5596885a9f333979418b35001ccaryclark    if (*stepPtr != foundStep) {
1513ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return set_last(last, endSpan);
151407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1515ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(*startPtr);
1516ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (!otherEnd) {
151765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark        return NULL;
151865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark    }
151965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark//    SkASSERT(otherEnd >= 0);
1520ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast();
1521ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* foundMin = foundSpan->starter(otherEnd);
1522ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (foundMin->windValue() != origMin->windValue()
1523ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            || foundMin->oppValue() != origMin->oppValue()) {
1524ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark          return set_last(last, endSpan);
1525dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
1526ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *startPtr = foundSpan;
1527dac1d17027dcaa5596885a9f333979418b35001ccaryclark    *stepPtr = foundStep;
1528dac1d17027dcaa5596885a9f333979418b35001ccaryclark    if (minPtr) {
1529dac1d17027dcaa5596885a9f333979418b35001ccaryclark        *minPtr = foundMin;
1530a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
153107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return other;
153207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
153307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1534ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic void clear_visited(SkOpSpan* span) {
1535ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // reset visited flag back to false
1536ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
1537ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
1538ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        while ((ptT = ptT->next()) != stopPtT) {
1539ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSegment* opp = ptT->segment();
1540ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            opp->resetVisited();
154107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1542ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((span = span->next()->upCastable()));
154307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
154407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1545ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// look for pairs of undetected coincident curves
1546ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// assumes that segments going in have visited flag clear
1547ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// curve/curve intersection should now do a pretty good job of finding coincident runs so
1548ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// this may be only be necessary for line/curve pairs -- so skip unless this is a line and the
1549ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// the opp is not a line
1550ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) {
1551ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (this->verb() != SkPath::kLine_Verb) {
1552ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return;
1553ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
1554ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* prior = NULL;
1555ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* span = &fHead;
1556ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
1557ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpPtT* ptT = span->ptT(), * spanStopPtT = ptT;
1558ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkASSERT(ptT->span() == span);
1559ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        while ((ptT = ptT->next()) != spanStopPtT) {
1560ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSegment* opp = ptT->span()->segment();
1561ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (opp->setVisited()) {
1562570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                continue;
1563570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
1564ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (opp->verb() == SkPath::kLine_Verb) {
1565ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1566ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1567ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (span->containsCoincidence(opp)) { // FIXME: this assumes that if the opposite
1568ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                                  // segment is coincident then no more coincidence
1569ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                                  // needs to be detected. This may not be true.
1570ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1571ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1572ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (span->containsCoinEnd(opp)) {
1573ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1574ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1575ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            // if already visited and visited again, check for coin
1576ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (span == &fHead) {
1577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1578ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1579ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* priorPtT = NULL, * priorStopPtT;
1580ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            // find prior span containing opp segment
1581ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSegment* priorOpp = NULL;
1582ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            prior = span;
1583ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            while (!priorOpp && (prior = prior->prev())) {
1584ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                priorStopPtT = priorPtT = prior->ptT();
1585ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                while ((priorPtT = priorPtT->next()) != priorStopPtT) {
1586ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    SkOpSegment* segment = priorPtT->span()->segment();
1587ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (segment == opp) {
1588ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        priorOpp = opp;
1589ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        break;
1590ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
1591ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                }
1592ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1593ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!priorOpp) {
1594ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1595ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1596ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* oppStart = prior->ptT();
1597ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* oppEnd = span->ptT();
1598ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            bool swapped = priorPtT->fT > ptT->fT;
1599ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (swapped) {
1600ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkTSwap(priorPtT, ptT);
1601ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkTSwap(oppStart, oppEnd);
1602ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1603ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            bool flipped = oppStart->fT > oppEnd->fT;
1604ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            bool coincident;
1605ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) {
1606ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                goto swapBack;
1607ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1608ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            {
1609ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                // average t, find mid pt
1610ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                double midT = (prior->t() + span->t()) / 2;
1611ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkPoint midPt = this->ptAtT(midT);
1612ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                coincident = true;
1613ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                // if the mid pt is not near either end pt, project perpendicular through opp seg
1614ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt)
1615ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) {
1616ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    coincident = false;
1617ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    SkIntersections i;
1618ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    int ptCount = SkPathOpsVerbToPoints(this->verb());
1619ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    SkVector dxdy = (*CurveSlopeAtT[ptCount])(pts(), midT);
1620ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    SkDLine ray = {{{midPt.fX, midPt.fY},
1621ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            {midPt.fX + dxdy.fY, midPt.fY - dxdy.fX}}};
1622ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    int oppPtCount = SkPathOpsVerbToPoints(opp->verb());
1623ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    (*CurveIntersectRay[oppPtCount])(opp->pts(), ray, &i);
1624ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    // measure distance and see if it's small enough to denote coincidence
1625ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    for (int index = 0; index < i.used(); ++index) {
1626ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        SkDPoint oppPt = i.pt(index);
1627ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        if (oppPt.approximatelyEqual(midPt)) {
1628ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            SkVector oppDxdy = (*CurveSlopeAtT[oppPtCount])(opp->pts(),
1629ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                    i[index][0]);
1630ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            oppDxdy.normalize();
1631ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            dxdy.normalize();
1632ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy) / FLT_EPSILON);
1633ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            coincident |= flatness < 5000;  // FIXME: replace with tuned value
1634ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        }
1635ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
1636ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                }
1637ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1638ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (coincident) {
1639ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            // mark coincidence
1640ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator);
1641ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                clear_visited(&fHead);
1642ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                missingCoincidence(coincidences, allocator);
1643ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                return;
1644ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1645ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    swapBack:
1646ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (swapped) {
1647ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkTSwap(priorPtT, ptT);
1648ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1649570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
1650ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((span = span->next()->upCastable()));
1651ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    clear_visited(&fHead);
1652ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1653ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1654ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later.
1655ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::moveNearby() {
1656ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
1657ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* spanS = &fHead;
1658ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
1659ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* test = spanS->upCast()->next();
1660ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpSpanBase* next;
1661ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (spanS->contains(test)) {
1662ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!test->final()) {
1663ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                test->upCast()->detach(spanS->ptT());
1664ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1665ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            } else if (spanS != &fHead) {
1666ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                spanS->upCast()->detach(test->ptT());
1667ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                spanS = test;
1668570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                continue;
1669570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
167007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1671ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        do {  // iterate through all spans associated with start
1672ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpPtT* startBase = spanS->ptT();
1673ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            next = test->final() ? NULL : test->upCast()->next();
1674ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            do {
1675ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                SkOpPtT* testBase = test->ptT();
1676ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                do {
1677ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (startBase == testBase) {
1678ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        goto checkNextSpan;
1679ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
1680ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (testBase->duplicate()) {
1681ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        continue;
1682ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
1683ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) {
1684ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        if (test == &this->fTail) {
1685ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            if (spanS == &fHead) {
1686ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                debugValidate();
1687ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                return true;  // if this span has collapsed, remove it from parent
1688ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            }
1689ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            this->fTail.merge(spanS->upCast());
1690ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            debugValidate();
1691ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            return true;
1692ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        }
1693ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        spanS->merge(test->upCast());
1694ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        spanS->upCast()->setNext(next);
1695ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        goto checkNextSpan;
1696ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
1697ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                } while ((testBase = testBase->next()) != test->ptT());
1698ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            } while ((startBase = startBase->next()) != spanS->ptT());
1699ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    checkNextSpan:
1700ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            ;
1701ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        } while ((test = next));
1702ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        spanS = spanS->upCast()->next();
1703ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while (!spanS->final());
1704ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    debugValidate();
1705ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return true;
170607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
170707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1708ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::operand() const {
1709ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return fContour->operand();
1710dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
1711dac1d17027dcaa5596885a9f333979418b35001ccaryclark
1712ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::oppXor() const {
1713ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return fContour->oppXor();
17145e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark}
17155e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark
1716ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const {
1717ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (fVerb == SkPath::kLine_Verb) {
1718ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        return false;
1719dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
1720ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // quads (and cubics) can loop back to nearly a line so that an opposite curve
1721ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // hits in two places with very different t values.
1722ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // OPTIMIZATION: curves could be preflighted so that, for example, something like
1723ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // 'controls contained by ends' could avoid this check for common curves
1724ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // 'ends are extremes in x or y' is cheaper to compute and real-world common
1725ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    // on the other hand, the below check is relatively inexpensive
1726ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double midT = (t1 + t2) / 2;
1727ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkPoint midPt = this->ptAtT(midT);
1728ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double seDistSq = SkTMax(pt1.distanceToSqd(pt2) * 2, FLT_EPSILON * 2);
1729ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return midPt.distanceToSqd(pt1) > seDistSq || midPt.distanceToSqd(pt2) > seDistSq;
1730ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1731ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1732ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding,
1733ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int* maxWinding, int* sumWinding) {
1734ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int deltaSum = SpanSign(start, end);
1735ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *maxWinding = *sumMiWinding;
1736ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *sumWinding = *sumMiWinding -= deltaSum;
1737ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
1738dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
1739dac1d17027dcaa5596885a9f333979418b35001ccaryclark
1740ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding,
1741ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding,
1742ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        int* oppSumWinding) {
1743ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int deltaSum = SpanSign(start, end);
1744ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppDeltaSum = OppSign(start, end);
174507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
174607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *maxWinding = *sumSuWinding;
174707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *sumWinding = *sumSuWinding -= deltaSum;
174807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppMaxWinding = *sumMiWinding;
174907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppSumWinding = *sumMiWinding -= oppDeltaSum;
175007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
175107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *maxWinding = *sumMiWinding;
175207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *sumWinding = *sumMiWinding -= deltaSum;
175307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppMaxWinding = *sumSuWinding;
175407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppSumWinding = *sumSuWinding -= oppDeltaSum;
175507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1756ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
1757ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM);
175807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
175907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
17604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::sortAngles() {
1761ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpanBase* span = &this->fHead;
17624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
1763ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle* fromAngle = span->fromAngle();
1764ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle* toAngle = span->final() ? NULL : span->upCast()->toAngle();
1765dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (!fromAngle && !toAngle) {
17664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
17674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1768cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#if DEBUG_ANGLE
17694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        bool wroteAfterHeader = false;
1770cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#endif
1771ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpAngle* baseAngle = fromAngle;
1772ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (fromAngle && toAngle) {
17734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE
1774ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(),
1775ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    span->debugID());
1776ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            wroteAfterHeader = true;
17774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
1778ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            fromAngle->insert(toAngle);
1779ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        } else if (!fromAngle) {
1780ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            baseAngle = toAngle;
178107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1782ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
17834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        do {
1784ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpSpanBase* oSpan = ptT->span();
1785ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (oSpan == span) {
1786ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                continue;
1787ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            }
1788ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            SkOpAngle* oAngle = oSpan->fromAngle();
1789dac1d17027dcaa5596885a9f333979418b35001ccaryclark            if (oAngle) {
1790570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_ANGLE
17914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                if (!wroteAfterHeader) {
1792ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
1793ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                            span->t(), span->debugID());
17944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                    wroteAfterHeader = true;
17954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
1796570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
1797ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (!oAngle->loopContains(baseAngle)) {
17988cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                    baseAngle->insert(oAngle);
17998cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                }
18004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
1801ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (!oSpan->final()) {
1802ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                oAngle = oSpan->upCast()->toAngle();
1803ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                if (oAngle) {
18044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE
1805ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (!wroteAfterHeader) {
1806ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
1807ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                                span->t(), span->debugID());
1808ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        wroteAfterHeader = true;
1809ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
18104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
1811ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    if (!oAngle->loopContains(baseAngle)) {
1812ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                        baseAngle->insert(oAngle);
1813ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    }
18148cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                }
18154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
1816ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        } while ((ptT = ptT->next()) != stopPtT);
1817ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (baseAngle->loopCount() == 1) {
1818ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            span->setFromAngle(NULL);
1819ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            if (toAngle) {
1820ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                span->upCast()->setToAngle(NULL);
18214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
18224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            baseAngle = NULL;
18234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
18244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
18254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
18264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
1827ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while (!span->final() && (span = span->upCast()->next()));
1828570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1829570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1830cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed
1831ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end,
1832ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkPoint edge[4]) const {
1833cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    SkASSERT(start != end);
1834ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpPtT& startPtT = *start->ptT();
1835ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpPtT& endPtT = *end->ptT();
1836ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    edge[0] = startPtT.fPt;
1837cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    int points = SkPathOpsVerbToPoints(fVerb);
1838ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    edge[points] = endPtT.fPt;
1839cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kLine_Verb) {
1840cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1841cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1842ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double startT = startPtT.fT;
1843ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double endT = endPtT.fT;
1844cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) {
1845cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        // don't compute midpoints if we already have them
184607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (fVerb == SkPath::kQuad_Verb) {
1847cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            edge[1] = fPts[1];
1848cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
184907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1850cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1851cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        if (start < end) {
1852cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            edge[1] = fPts[1];
1853cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            edge[2] = fPts[2];
1854cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1855cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
1856cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        edge[1] = fPts[2];
1857cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        edge[2] = fPts[1];
1858cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1859cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1860cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    const SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[points].fX, edge[points].fY }};
1861cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kQuad_Verb) {
1862cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoint();
1863cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    } else {
1864cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1865cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDPoint ctrl[2];
1866cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl);
1867cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        edge[1] = ctrl[0].asSkPoint();
1868cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        edge[2] = ctrl[1].asSkPoint();
186907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1870cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    return true;
1871cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com}
1872cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
1873ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end,
1874ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkDCubic* result) const {
1875cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    SkASSERT(start != end);
1876ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpPtT& startPtT = *start->ptT();
1877ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpPtT& endPtT = *end->ptT();
1878ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (*result)[0].set(startPtT.fPt);
1879cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    int points = SkPathOpsVerbToPoints(fVerb);
1880ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    (*result)[points].set(endPtT.fPt);
1881cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kLine_Verb) {
1882cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1883cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1884ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double startT = startPtT.fT;
1885ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    double endT = endPtT.fT;
1886cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) {
1887cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        // don't compute midpoints if we already have them
1888cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        if (fVerb == SkPath::kQuad_Verb) {
1889cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            (*result)[1].set(fPts[1]);
1890cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1891cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
1892cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1893ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (startT == 0) {
1894cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            (*result)[1].set(fPts[1]);
1895cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            (*result)[2].set(fPts[2]);
1896cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1897cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
1898cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        (*result)[1].set(fPts[2]);
1899cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        (*result)[2].set(fPts[1]);
1900cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1901cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1902cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kQuad_Verb) {
1903cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        (*result)[1] = SkDQuad::SubDivide(fPts, (*result)[0], (*result)[2], startT, endT);
1904cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    } else {
1905cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1906cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDCubic::SubDivide(fPts, (*result)[0], (*result)[3], startT, endT, &(*result)[1]);
1907cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1908cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    return true;
190907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
191007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1911ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end,
1912ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkPathOpsBounds* bounds) const {
191307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPoint edge[4];
191407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    subDivide(start, end, edge);
1915277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge);
191607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
191707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1918ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) {
1919ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkOpSpan* span = this->head();
1920ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    do {
1921ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        if (!span->done()) {
192207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            break;
192307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1924ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    } while ((span = span->next()->upCastable()));
1925ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    SkASSERT(span);
1926ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *start = span;
1927ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    *end = span->next();
192807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
192907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1930ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
1931ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpan* lesser = start->starter(end);
1932ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppWinding = lesser->oppSum();
1933ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int oppSpanWinding = SkOpSegment::OppSign(start, end);
193407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding)
193507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            && oppWinding != SK_MaxS32) {
193607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        oppWinding -= oppSpanWinding;
193707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
193807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return oppWinding;
193907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
194007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
194107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(const SkOpAngle* angle) const {
1942ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* startSpan = angle->start();
1943ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* endSpan = angle->end();
1944ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return updateOppWinding(endSpan, startSpan);
194507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
194607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
194707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const {
1948ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* startSpan = angle->start();
1949ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* endSpan = angle->end();
1950ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return updateOppWinding(startSpan, endSpan);
195107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
195207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1953ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::updateWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
1954ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpan* lesser = start->starter(end);
1955ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int winding = lesser->windSum();
19568cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    if (winding == SK_MinS32) {
19578cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        return winding;
19588cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    }
1959ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int spanWinding = SkOpSegment::SpanSign(start, end);
1960570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (winding && UseInnerWinding(winding - spanWinding, winding)
1961570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            && winding != SK_MaxS32) {
196207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        winding -= spanWinding;
196307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
196407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return winding;
196507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
196607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
196707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWinding(const SkOpAngle* angle) const {
1968ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* startSpan = angle->start();
1969ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* endSpan = angle->end();
1970ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return updateWinding(endSpan, startSpan);
1971570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1972570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
197307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWindingReverse(const SkOpAngle* angle) const {
1974ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* startSpan = angle->start();
1975ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpanBase* endSpan = angle->end();
1976ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return updateWinding(startSpan, endSpan);
1977570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1978570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1979570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// OPTIMIZATION: does the following also work, and is it any faster?
1980570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// return outerWinding * innerWinding > 0
1981570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com//      || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
1982570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) {
1983570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkASSERT(outerWinding != SK_MaxS32);
1984570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkASSERT(innerWinding != SK_MaxS32);
1985570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int absOut = abs(outerWinding);
1986570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int absIn = abs(innerWinding);
1987570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
1988570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    return result;
1989570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1990570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1991ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::windingAtT(double tHit, const SkOpSpan* span, bool crossOpp,
1992ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        SkScalar* dx) const {
1993ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    if (approximately_zero(tHit - span->t())) {  // if we hit the end of a span, disregard
199407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return SK_MinS32;
199507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1996ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int winding = crossOpp ? span->oppSum() : span->windSum();
199707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(winding != SK_MinS32);
1998ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    int windVal = crossOpp ? span->oppValue() : span->windValue();
199907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T
2000dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __FUNCTION__,
2001ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            debugID(), crossOpp, tHit, span->t(), winding, windVal);
200207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
200307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // see if a + change in T results in a +/- change in X (compute x'(T))
2004277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
200507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) {
200607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *dx = fPts[2].fX - fPts[1].fX - *dx;
200707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
200807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (*dx == 0) {
200907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T
201007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf(" dx=0 winding=SK_MinS32\n");
201107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
201207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return SK_MinS32;
201307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2014a4aced47281e085201a356ce888b92138846e9f6skia.committer@gmail.com    if (windVal < 0) {  // reverse sign if opp contour traveled in reverse
201507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com            *dx = -*dx;
201607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
201707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (winding * *dx > 0) {  // if same signs, result is negative
201807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        winding += *dx > 0 ? -windVal : windVal;
201907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
202007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T
202107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding);
202207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
202307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return winding;
202407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
202507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
202607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windSum(const SkOpAngle* angle) const {
2027ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const SkOpSpan* minSpan = angle->start()->starter(angle->end());
2028ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return minSpan->windSum();
202907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
2030