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 */
754359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpCoincidence.h"
8dac1d17027dcaa5596885a9f333979418b35001ccaryclark#include "SkOpContour.h"
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h"
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h"
1154359294a7c9dc54802d512a5d891a35c1663392caryclark
1254359294a7c9dc54802d512a5d891a35c1663392caryclark/*
1354359294a7c9dc54802d512a5d891a35c1663392caryclarkAfter computing raw intersections, post process all segments to:
1454359294a7c9dc54802d512a5d891a35c1663392caryclark- find small collections of points that can be collapsed to a single point
1554359294a7c9dc54802d512a5d891a35c1663392caryclark- find missing intersections to resolve differences caused by different algorithms
1654359294a7c9dc54802d512a5d891a35c1663392caryclark
1754359294a7c9dc54802d512a5d891a35c1663392caryclarkConsider segments containing tiny or small intervals. Consider coincident segments
1854359294a7c9dc54802d512a5d891a35c1663392caryclarkbecause coincidence finds intersections through distance measurement that non-coincident
1954359294a7c9dc54802d512a5d891a35c1663392caryclarkintersection tests cannot.
2054359294a7c9dc54802d512a5d891a35c1663392caryclark */
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
3154359294a7c9dc54802d512a5d891a35c1663392caryclarkstatic const bool gActiveEdge[kXOR_SkPathOp + 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
4554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr,
46bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkOpSpanBase** endPtr, bool* done) {
47bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) {
484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return result;
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
50bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) {
5154359294a7c9dc54802d512a5d891a35c1663392caryclark        return result;
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
5396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr,
57bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkOpSpanBase** endPtr, bool* done) {
5854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* upSpan = start->upCastable();
5954359294a7c9dc54802d512a5d891a35c1663392caryclark    if (upSpan) {
6054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (upSpan->windValue() || upSpan->oppValue()) {
6154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSpanBase* next = upSpan->next();
6254359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!*endPtr) {
6354359294a7c9dc54802d512a5d891a35c1663392caryclark                *startPtr = start;
6454359294a7c9dc54802d512a5d891a35c1663392caryclark                *endPtr = next;
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
6654359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!upSpan->done()) {
6754359294a7c9dc54802d512a5d891a35c1663392caryclark                if (upSpan->windSum() != SK_MinS32) {
6854359294a7c9dc54802d512a5d891a35c1663392caryclark                    return spanToAngle(start, next);
694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                *done = false;
714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
7354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(upSpan->done());
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* downSpan = start->prev();
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // edge leading into junction
7854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (downSpan) {
7954359294a7c9dc54802d512a5d891a35c1663392caryclark        if (downSpan->windValue() || downSpan->oppValue()) {
8054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!*endPtr) {
8154359294a7c9dc54802d512a5d891a35c1663392caryclark                *startPtr = start;
8254359294a7c9dc54802d512a5d891a35c1663392caryclark                *endPtr = downSpan;
8354359294a7c9dc54802d512a5d891a35c1663392caryclark            }
8454359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!downSpan->done()) {
8554359294a7c9dc54802d512a5d891a35c1663392caryclark                if (downSpan->windSum() != SK_MinS32) {
8654359294a7c9dc54802d512a5d891a35c1663392caryclark                    return spanToAngle(start, downSpan);
874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                *done = false;
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
9154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(downSpan->done());
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
9754359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr,
98bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkOpSpanBase** endPtr, bool* done) {
9954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* oPtT = start->ptT()->next();
10054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* other = oPtT->segment();
10154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* oSpan = oPtT->span();
102bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    return other->activeAngleInner(oSpan, startPtr, endPtr, done);
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask,
10654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkPathOp op) {
10754359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumMiWinding = this->updateWinding(end, start);
10854359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumSuWinding = this->updateOppWinding(end, start);
10965f553182ab7069378ef863d30094d0327f178d0caryclark#if DEBUG_LIMIT_WIND_SUM
11065f553182ab7069378ef863d30094d0327f178d0caryclark    SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM);
11165f553182ab7069378ef863d30094d0327f178d0caryclark    SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM);
11265f553182ab7069378ef863d30094d0327f178d0caryclark#endif
11354359294a7c9dc54802d512a5d891a35c1663392caryclark    if (this->operand()) {
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkTSwap<int>(sumMiWinding, sumSuWinding);
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11654359294a7c9dc54802d512a5d891a35c1663392caryclark    return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding);
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end,
12054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkPathOp op, int* sumMiWinding, int* sumSuWinding) {
1214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
12254359294a7c9dc54802d512a5d891a35c1663392caryclark    this->setUpWindings(start, end, sumMiWinding, sumSuWinding,
1234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool miFrom;
12507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool miTo;
12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool suFrom;
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool suTo;
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
1294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miFrom = (oppMaxWinding & xorMiMask) != 0;
1304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miTo = (oppSumWinding & xorMiMask) != 0;
1314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suFrom = (maxWinding & xorSuMask) != 0;
1324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suTo = (sumWinding & xorSuMask) != 0;
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
1344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miFrom = (maxWinding & xorMiMask) != 0;
1354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        miTo = (sumWinding & xorMiMask) != 0;
1364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suFrom = (oppMaxWinding & xorSuMask) != 0;
1374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        suTo = (oppSumWinding & xorSuMask) != 0;
13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ACTIVE_OP
141dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n",
14254359294a7c9dc54802d512a5d891a35c1663392caryclark            __FUNCTION__, debugID(), start->t(), end->t(),
143570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return result;
14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14854359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end) {
14954359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumWinding = updateWinding(end, start);
15054359294a7c9dc54802d512a5d891a35c1663392caryclark    return activeWinding(start, end, &sumWinding);
15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding) {
1544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int maxWinding;
15554359294a7c9dc54802d512a5d891a35c1663392caryclark    setUpWinding(start, end, &maxWinding, sumWinding);
1564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool from = maxWinding != 0;
15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool to = *sumWinding  != 0;
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool result = gUnaryActiveEdge[from][to];
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return result;
16007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
16227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkvoid SkOpSegment::addAlignIntersection(SkOpPtT& endPtT, SkPoint& oldPt,
16327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkOpContourHead* contourList, SkChunkAlloc* allocator) {
16427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    const SkPoint& newPt = endPtT.fPt;
16527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    if (newPt == oldPt) {
16627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        return;
16727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    }
16827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    SkPoint line[2] = { newPt, oldPt };
16927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    SkPathOpsBounds lineBounds;
17027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    lineBounds.setBounds(line, 2);
17127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    SkDLine aLine;
17227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    aLine.set(line);
17327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    SkOpContour* current = contourList;
17427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    do {
17527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        if (!SkPathOpsBounds::Intersects(current->bounds(), lineBounds)) {
17627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            continue;
17727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        }
17827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkOpSegment* segment = current->first();
17927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        do {
18027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (!SkPathOpsBounds::Intersects(segment->bounds(), lineBounds)) {
18127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
18227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
18327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (newPt == segment->fPts[0]) {
18427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
18527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
18627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (newPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) {
18727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
18827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
18927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (oldPt == segment->fPts[0]) {
19027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
19127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
19227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (oldPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) {
19327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
19427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
19527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (endPtT.contains(segment)) {
19627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                continue;
19727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
19827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            SkIntersections i;
19927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            switch (segment->fVerb) {
20027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                case SkPath::kLine_Verb: {
20127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    SkDLine bLine;
20227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    bLine.set(segment->fPts);
20327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    i.intersect(bLine, aLine);
20427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    } break;
20527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                case SkPath::kQuad_Verb: {
20627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    SkDQuad bQuad;
20727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    bQuad.set(segment->fPts);
20827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    i.intersect(bQuad, aLine);
20927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    } break;
21027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                case SkPath::kConic_Verb: {
21127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    SkDConic bConic;
21227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    bConic.set(segment->fPts, segment->fWeight);
21327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    i.intersect(bConic, aLine);
21427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    } break;
21527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                case SkPath::kCubic_Verb: {
21627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    SkDCubic bCubic;
21727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    bCubic.set(segment->fPts);
21827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    i.intersect(bCubic, aLine);
21927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    } break;
22027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                default:
22127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    SkASSERT(0);
22227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
22327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (i.used()) {
22427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkASSERT(i.used() == 1);
22527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkASSERT(!zero_or_one(i[0][0]));
22627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkOpSpanBase* checkSpan = fHead.next();
22727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                while (!checkSpan->final()) {
22827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    if (checkSpan->contains(segment)) {
22927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                        goto nextSegment;
23027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    }
23127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                    checkSpan = checkSpan->upCast()->next();
23227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                }
23327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkOpPtT* ptT = segment->addT(i[0][0], SkOpSegment::kAllowAlias, allocator);
23427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                ptT->fPt = newPt;
23527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                endPtT.addOpp(ptT);
23627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
23727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    nextSegment:
23827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            ;
23927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        } while ((segment = segment->next()));
24027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    } while ((current = current->next()));
24127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark}
24227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
243ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkbool SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end,
244ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkPathWriter* path) const {
245ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    if (start->starter(end)->alreadyAdded()) {
246ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        return false;
247ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
2481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkOpCurve edge;
24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint* ePtr;
2501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkScalar eWeight;
25154359294a7c9dc54802d512a5d891a35c1663392caryclark    if ((start == &fHead && end == &fTail) || (start == &fTail && end == &fHead)) {
25207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        ePtr = fPts;
2531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        eWeight = fWeight;
25407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
25507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZE? if not active, skip remainder and return xyAtT(end)
2561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        subDivide(start, end, &edge);
2571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        ePtr = edge.fPts;
2581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        eWeight = edge.fWeight;
25907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
260ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bool reverse = ePtr == fPts && start != &fHead;
261ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    if (reverse) {
262ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]);
263ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        switch (fVerb) {
264ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kLine_Verb:
265ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->deferredLine(ePtr[0]);
266ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
267ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kQuad_Verb:
268ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->quadTo(ePtr[1], ePtr[0]);
269ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
270ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kConic_Verb:
271ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->conicTo(ePtr[1], ePtr[0], eWeight);
272ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
273ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kCubic_Verb:
274ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->cubicTo(ePtr[2], ePtr[1], ePtr[0]);
275ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
276ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            default:
277ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                SkASSERT(0);
278ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        }
279ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    } else {
280ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        path->deferredMoveLine(ePtr[0]);
281ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        switch (fVerb) {
282ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kLine_Verb:
283ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->deferredLine(ePtr[1]);
284ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
285ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kQuad_Verb:
286ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->quadTo(ePtr[1], ePtr[2]);
287ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
288ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kConic_Verb:
289ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->conicTo(ePtr[1], ePtr[2], eWeight);
290ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
291ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            case SkPath::kCubic_Verb:
292ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                path->cubicTo(ePtr[1], ePtr[2], ePtr[3]);
293ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                break;
294ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            default:
295ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                SkASSERT(0);
29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
298ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    return true;
29907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
30007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
30154359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* allocator) {
30296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpanBase* existing = nullptr;
30354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* test = &fHead;
30454359294a7c9dc54802d512a5d891a35c1663392caryclark    double testT;
3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
30654359294a7c9dc54802d512a5d891a35c1663392caryclark        if ((testT = test->ptT()->fT) >= t) {
30754359294a7c9dc54802d512a5d891a35c1663392caryclark            if (testT == t) {
30854359294a7c9dc54802d512a5d891a35c1663392caryclark                existing = test;
30954359294a7c9dc54802d512a5d891a35c1663392caryclark            }
31054359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
31154359294a7c9dc54802d512a5d891a35c1663392caryclark        }
31254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((test = test->upCast()->next()));
31354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* result;
31454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (existing && existing->contains(opp)) {
31554359294a7c9dc54802d512a5d891a35c1663392caryclark        result = existing->ptT();
31654359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
31754359294a7c9dc54802d512a5d891a35c1663392caryclark        result = this->addT(t, SkOpSegment::kNoAlias, allocator);
31807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
31954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(result);
32054359294a7c9dc54802d512a5d891a35c1663392caryclark    return result;
32107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
32207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
32354359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpSegment::addT(double t, AllowAlias allowAlias, SkChunkAlloc* allocator) {
32454359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
32554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkPoint pt = this->ptAtT(t);
32654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* span = &fHead;
3274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
32854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* result = span->ptT();
32908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        SkOpPtT* loop;
33008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        bool duplicatePt;
33154359294a7c9dc54802d512a5d891a35c1663392caryclark        if (t == result->fT) {
33208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            goto bumpSpan;
33354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
33454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (this->match(result, this, t, pt)) {
33554359294a7c9dc54802d512a5d891a35c1663392caryclark            // see if any existing alias matches segment, pt, and t
33608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark           loop = result->next();
33708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            duplicatePt = false;
33854359294a7c9dc54802d512a5d891a35c1663392caryclark            while (loop != result) {
33954359294a7c9dc54802d512a5d891a35c1663392caryclark                bool ptMatch = loop->fPt == pt;
34054359294a7c9dc54802d512a5d891a35c1663392caryclark                if (loop->segment() == this && loop->fT == t && ptMatch) {
34108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    goto bumpSpan;
34254359294a7c9dc54802d512a5d891a35c1663392caryclark                }
34354359294a7c9dc54802d512a5d891a35c1663392caryclark                duplicatePt |= ptMatch;
34454359294a7c9dc54802d512a5d891a35c1663392caryclark                loop = loop->next();
34554359294a7c9dc54802d512a5d891a35c1663392caryclark            }
34654359294a7c9dc54802d512a5d891a35c1663392caryclark            if (kNoAlias == allowAlias) {
34708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    bumpSpan:
34808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                span->bumpSpanAdds();
34954359294a7c9dc54802d512a5d891a35c1663392caryclark                return result;
35054359294a7c9dc54802d512a5d891a35c1663392caryclark            }
35154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator);
35254359294a7c9dc54802d512a5d891a35c1663392caryclark            alias->init(result->span(), t, pt, duplicatePt);
35354359294a7c9dc54802d512a5d891a35c1663392caryclark            result->insert(alias);
35454359294a7c9dc54802d512a5d891a35c1663392caryclark            result->span()->unaligned();
35554359294a7c9dc54802d512a5d891a35c1663392caryclark            this->debugValidate();
35654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ADD_T
35754359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n",  __FUNCTION__, t,
35854359294a7c9dc54802d512a5d891a35c1663392caryclark                    alias->segment()->debugID(), alias->span()->debugID());
35954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
36008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            span->bumpSpanAdds();
36154359294a7c9dc54802d512a5d891a35c1663392caryclark            return alias;
36254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
36354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (t < result->fT) {
36454359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSpan* prev = result->span()->prev();
365a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark            if (!prev) {
366a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark                return nullptr;
367a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark            }
36854359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSpan* span = insert(prev, allocator);
36954359294a7c9dc54802d512a5d891a35c1663392caryclark            span->init(this, prev, t, pt);
37054359294a7c9dc54802d512a5d891a35c1663392caryclark            this->debugValidate();
37154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ADD_T
37254359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t,
37354359294a7c9dc54802d512a5d891a35c1663392caryclark                    span->segment()->debugID(), span->debugID());
37454359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
37508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            span->bumpSpanAdds();
37654359294a7c9dc54802d512a5d891a35c1663392caryclark            return span->ptT();
37754359294a7c9dc54802d512a5d891a35c1663392caryclark        }
37854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(span != &fTail);
37954359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((span = span->upCast()->next()));
38054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(0);
38196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
3824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
3834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
38454359294a7c9dc54802d512a5d891a35c1663392caryclark// choose a solitary t and pt value; remove aliases; align the opposite ends
38554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::align() {
38654359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
38754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* span = &fHead;
38854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!span->aligned()) {
38954359294a7c9dc54802d512a5d891a35c1663392caryclark        span->alignEnd(0, fPts[0]);
39054359294a7c9dc54802d512a5d891a35c1663392caryclark    }
39154359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((span = span->upCast()->next())) {
39254359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span == &fTail) {
39307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            break;
39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
39554359294a7c9dc54802d512a5d891a35c1663392caryclark        span->align();
39607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
39754359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!span->aligned()) {
39854359294a7c9dc54802d512a5d891a35c1663392caryclark        span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]);
39907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
400bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    if (this->collapsed()) {
401bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkOpSpan* span = &fHead;
402bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        do {
403bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            span->setWindValue(0);
404bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            span->setOppValue(0);
405bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            this->markDone(span);
406bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        } while ((span = span->next()->upCastable()));
407bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    }
40854359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
40954359294a7c9dc54802d512a5d891a35c1663392caryclark}
41054359294a7c9dc54802d512a5d891a35c1663392caryclark
41154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::calcAngles(SkChunkAlloc* allocator) {
41254359294a7c9dc54802d512a5d891a35c1663392caryclark    bool activePrior = !fHead.isCanceled();
41354359294a7c9dc54802d512a5d891a35c1663392caryclark    if (activePrior && !fHead.simple()) {
41454359294a7c9dc54802d512a5d891a35c1663392caryclark        addStartSpan(allocator);
4150dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
41654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* prior = &fHead;
41754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* spanBase = fHead.next();
41854359294a7c9dc54802d512a5d891a35c1663392caryclark    while (spanBase != &fTail) {
41954359294a7c9dc54802d512a5d891a35c1663392caryclark        if (activePrior) {
42054359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpAngle* priorAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
42154359294a7c9dc54802d512a5d891a35c1663392caryclark            priorAngle->set(spanBase, prior);
42254359294a7c9dc54802d512a5d891a35c1663392caryclark            spanBase->setFromAngle(priorAngle);
423ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark        }
42454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpan* span = spanBase->upCast();
42554359294a7c9dc54802d512a5d891a35c1663392caryclark        bool active = !span->isCanceled();
42654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase* next = span->next();
42754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (active) {
42854359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
42954359294a7c9dc54802d512a5d891a35c1663392caryclark            angle->set(span, next);
43054359294a7c9dc54802d512a5d891a35c1663392caryclark            span->setToAngle(angle);
43154359294a7c9dc54802d512a5d891a35c1663392caryclark        }
43254359294a7c9dc54802d512a5d891a35c1663392caryclark        activePrior = active;
43354359294a7c9dc54802d512a5d891a35c1663392caryclark        prior = span;
43454359294a7c9dc54802d512a5d891a35c1663392caryclark        spanBase = next;
4354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
43654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (activePrior && !fTail.simple()) {
43754359294a7c9dc54802d512a5d891a35c1663392caryclark        addEndSpan(allocator);
4384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
43965f553182ab7069378ef863d30094d0327f178d0caryclark}
44065f553182ab7069378ef863d30094d0327f178d0caryclark
441bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclarkbool SkOpSegment::collapsed() const {
442bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt();
443bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark}
444bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark
44554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
44654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpAngle::IncludeType includeType) {
447624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSegment* baseSegment = baseAngle->segment();
44854359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
44954359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumSuWinding;
45054359294a7c9dc54802d512a5d891a35c1663392caryclark    bool binary = includeType >= SkOpAngle::kBinarySingle;
45154359294a7c9dc54802d512a5d891a35c1663392caryclark    if (binary) {
45254359294a7c9dc54802d512a5d891a35c1663392caryclark        sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle);
45354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (baseSegment->operand()) {
45454359294a7c9dc54802d512a5d891a35c1663392caryclark            SkTSwap<int>(sumMiWinding, sumSuWinding);
4550dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
45654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
45754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* nextSegment = nextAngle->segment();
45854359294a7c9dc54802d512a5d891a35c1663392caryclark    int maxWinding, sumWinding;
45954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* last;
46054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (binary) {
46154359294a7c9dc54802d512a5d891a35c1663392caryclark        int oppMaxWinding, oppSumWinding;
46254359294a7c9dc54802d512a5d891a35c1663392caryclark        nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
46354359294a7c9dc54802d512a5d891a35c1663392caryclark                &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
46454359294a7c9dc54802d512a5d891a35c1663392caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
46554359294a7c9dc54802d512a5d891a35c1663392caryclark                nextAngle);
4664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
46754359294a7c9dc54802d512a5d891a35c1663392caryclark        nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding,
46854359294a7c9dc54802d512a5d891a35c1663392caryclark                &maxWinding, &sumWinding);
46954359294a7c9dc54802d512a5d891a35c1663392caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
4704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
47154359294a7c9dc54802d512a5d891a35c1663392caryclark    nextAngle->setLastMarked(last);
4724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
4734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
474624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpSegment::ComputeOneSumReverse(SkOpAngle* baseAngle, SkOpAngle* nextAngle,
47554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpAngle::IncludeType includeType) {
476624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSegment* baseSegment = baseAngle->segment();
47754359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumMiWinding = baseSegment->updateWinding(baseAngle);
47854359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumSuWinding;
47954359294a7c9dc54802d512a5d891a35c1663392caryclark    bool binary = includeType >= SkOpAngle::kBinarySingle;
4800dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    if (binary) {
48154359294a7c9dc54802d512a5d891a35c1663392caryclark        sumSuWinding = baseSegment->updateOppWinding(baseAngle);
48254359294a7c9dc54802d512a5d891a35c1663392caryclark        if (baseSegment->operand()) {
48354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkTSwap<int>(sumMiWinding, sumSuWinding);
4840dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
4850dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
48654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* nextSegment = nextAngle->segment();
48754359294a7c9dc54802d512a5d891a35c1663392caryclark    int maxWinding, sumWinding;
48854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* last;
48954359294a7c9dc54802d512a5d891a35c1663392caryclark    if (binary) {
49054359294a7c9dc54802d512a5d891a35c1663392caryclark        int oppMaxWinding, oppSumWinding;
49154359294a7c9dc54802d512a5d891a35c1663392caryclark        nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
49254359294a7c9dc54802d512a5d891a35c1663392caryclark                &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
49354359294a7c9dc54802d512a5d891a35c1663392caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding,
49454359294a7c9dc54802d512a5d891a35c1663392caryclark                nextAngle);
4954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
49654359294a7c9dc54802d512a5d891a35c1663392caryclark        nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding,
49754359294a7c9dc54802d512a5d891a35c1663392caryclark                &maxWinding, &sumWinding);
49854359294a7c9dc54802d512a5d891a35c1663392caryclark        last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle);
4990dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
50054359294a7c9dc54802d512a5d891a35c1663392caryclark    nextAngle->setLastMarked(last);
5014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
5024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
503dac1d17027dcaa5596885a9f333979418b35001ccaryclark// at this point, the span is already ordered, or unorderable
50454359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end,
50554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpAngle::IncludeType includeType) {
5064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkASSERT(includeType != SkOpAngle::kUnaryXor);
50754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpAngle* firstAngle = this->spanToAngle(end, start);
50896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == firstAngle || nullptr == firstAngle->next()) {
5094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return SK_NaN32;
510570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
511570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    // if all angles have a computed winding,
512570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  or if no adjacent angles are orderable,
513570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  or if adjacent orderable angles have no computed winding,
514570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    //  there's nothing to do
515dac1d17027dcaa5596885a9f333979418b35001ccaryclark    // if two orderable angles are adjacent, and both are next to orderable angles,
516dac1d17027dcaa5596885a9f333979418b35001ccaryclark    //  and one has winding computed, transfer to the other
51796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpAngle* baseAngle = nullptr;
518570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool tryReverse = false;
519570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    // look for counterclockwise transfers
520dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* angle = firstAngle->previous();
521dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* next = angle->next();
522dac1d17027dcaa5596885a9f333979418b35001ccaryclark    firstAngle = next;
52307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
524dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkOpAngle* prior = angle;
525dac1d17027dcaa5596885a9f333979418b35001ccaryclark        angle = next;
526dac1d17027dcaa5596885a9f333979418b35001ccaryclark        next = angle->next();
527dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkASSERT(prior->next() == angle);
528dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkASSERT(angle->next() == next);
529dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
53096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            baseAngle = nullptr;
5314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
5324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
53354359294a7c9dc54802d512a5d891a35c1663392caryclark        int testWinding = angle->starter()->windSum();
534dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (SK_MinS32 != testWinding) {
535dac1d17027dcaa5596885a9f333979418b35001ccaryclark            baseAngle = angle;
5364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            tryReverse = true;
5374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
5384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
5394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (baseAngle) {
5404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            ComputeOneSum(baseAngle, angle, includeType);
54196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr;
5424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
543dac1d17027dcaa5596885a9f333979418b35001ccaryclark    } while (next != firstAngle);
54454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) {
5454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        firstAngle = baseAngle;
5464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        tryReverse = true;
5474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
5484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (tryReverse) {
54996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        baseAngle = nullptr;
550dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkOpAngle* prior = firstAngle;
551570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        do {
552dac1d17027dcaa5596885a9f333979418b35001ccaryclark            angle = prior;
553dac1d17027dcaa5596885a9f333979418b35001ccaryclark            prior = angle->previous();
554dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(prior->next() == angle);
555dac1d17027dcaa5596885a9f333979418b35001ccaryclark            next = angle->next();
556dac1d17027dcaa5596885a9f333979418b35001ccaryclark            if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
55796fcdcc219d2a0d3579719b84b28bede76efba64halcanary                baseAngle = nullptr;
558dac1d17027dcaa5596885a9f333979418b35001ccaryclark                continue;
559dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
56054359294a7c9dc54802d512a5d891a35c1663392caryclark            int testWinding = angle->starter()->windSum();
5614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (SK_MinS32 != testWinding) {
5624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                baseAngle = angle;
563570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                continue;
56407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
565570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            if (baseAngle) {
5664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                ComputeOneSumReverse(baseAngle, angle, includeType);
56796fcdcc219d2a0d3579719b84b28bede76efba64halcanary                baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr;
568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
569dac1d17027dcaa5596885a9f333979418b35001ccaryclark        } while (prior != firstAngle);
570570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
57154359294a7c9dc54802d512a5d891a35c1663392caryclark    return start->starter(end)->windSum();
57207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
57307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
57454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::detach(const SkOpSpan* span) {
57554359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->done()) {
57608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        --fDoneCount;
577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    }
57808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    --fCount;
57908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    SkASSERT(fCount >= fDoneCount);
5800dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed}
5810dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkdouble SkOpSegment::distSq(double t, const SkOpAngle* oppAngle) const {
58354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDPoint testPt = this->dPtAtT(t);
58454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDLine testPerp = {{ testPt, testPt }};
58554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDVector slope = this->dSlopeAtT(t);
58654359294a7c9dc54802d512a5d891a35c1663392caryclark    testPerp[1].fX += slope.fY;
58754359294a7c9dc54802d512a5d891a35c1663392caryclark    testPerp[1].fY -= slope.fX;
58854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkIntersections i;
58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* oppSegment = oppAngle->segment();
5901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    (*CurveIntersectRay[oppSegment->verb()])(oppSegment->pts(), oppSegment->weight(), testPerp, &i);
59154359294a7c9dc54802d512a5d891a35c1663392caryclark    double closestDistSq = SK_ScalarInfinity;
59254359294a7c9dc54802d512a5d891a35c1663392caryclark    for (int index = 0; index < i.used(); ++index) {
59354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) {
59454359294a7c9dc54802d512a5d891a35c1663392caryclark            continue;
5950dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
59654359294a7c9dc54802d512a5d891a35c1663392caryclark        double testDistSq = testPt.distanceSquared(i.pt(index));
59754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (closestDistSq > testDistSq) {
59854359294a7c9dc54802d512a5d891a35c1663392caryclark            closestDistSq = testDistSq;
5990dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
60054359294a7c9dc54802d512a5d891a35c1663392caryclark    }
60154359294a7c9dc54802d512a5d891a35c1663392caryclark    return closestDistSq;
6024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
6034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
604d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclarkvoid SkOpSegment::findCollapsed() {
605d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark    if (fHead.contains(&fTail)) {
606d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        markAllDone();
607d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        // move start and end to the same point
608d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        fHead.alignEnd(0, fHead.pt());
609d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark        fTail.setAligned();
610d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark    }
611d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark}
612d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark
61307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
61407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The M and S variable name parts stand for the operators.
61507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com   Mi stands for Minuend (see wiki subtraction, analogous to difference)
61607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com   Su stands for Subtrahend
61707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The Opp variable name part designates that the value is for the Opposite operator.
61807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Opposite values result from combining coincident spans.
61907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
62054359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart,
62154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) {
62254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* start = *nextStart;
62354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* end = *nextEnd;
62454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != end);
62554359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
62654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
62754359294a7c9dc54802d512a5d891a35c1663392caryclark    if (other) {
62807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // mark the smaller of startIndex, endIndex done, and all adjacent
62907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // spans with the same T value (but not 'other' spans)
63007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
63107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
63207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
63354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpan* startSpan = start->starter(end);
63454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (startSpan->done()) {
63596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
636cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
63754359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(startSpan);
63854359294a7c9dc54802d512a5d891a35c1663392caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
63907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
64007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
64154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
64254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear == end);  // is this ever not end?
64354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear);
64454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != endNear);
64554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
6464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // more than one viable candidate -- measure angles to find best
64754359294a7c9dc54802d512a5d891a35c1663392caryclark    int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp);
648570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool sortable = calcWinding != SK_NaN32;
6494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (!sortable) {
6507eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        *unsortable = true;
65154359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
65296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
6537eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    }
65454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
6554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (angle->unorderable()) {
65607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *unsortable = true;
65754359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
65896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
65907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
6614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
6624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
66307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
66454359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumMiWinding = updateWinding(end, start);
6658cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    if (sumMiWinding == SK_MinS32) {
6668cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        *unsortable = true;
66754359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
66896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
6698cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    }
67054359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumSuWinding = updateOppWinding(end, start);
67107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
67207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkTSwap<int>(sumMiWinding, sumSuWinding);
67307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
67596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpAngle* foundAngle = nullptr;
67607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
67707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // iterate through the angle, and compute everyone's winding
67807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
67907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
68007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
68107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
68207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
6834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
68407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (activeAngle) {
68507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++activeCount;
68607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (!foundAngle || (foundDone && activeCount & 1)) {
68707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundAngle = nextAngle;
688570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                foundDone = nextSegment->done(nextAngle);
68907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
69007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
69107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (nextSegment->done()) {
69207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            continue;
69307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
694570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (!activeAngle) {
69554359294a7c9dc54802d512a5d891a35c1663392caryclark            (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end());
696570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
69754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase* last = nextAngle->lastMarked();
69807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (last) {
6994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
70007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            *chase->append() = last;
70107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
70254359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
70354359294a7c9dc54802d512a5d891a35c1663392caryclark                    last->segment()->debugID(), last->debugID());
70454359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!last->final()) {
70554359294a7c9dc54802d512a5d891a35c1663392caryclark                SkDebugf(" windSum=%d", last->upCast()->windSum());
70654359294a7c9dc54802d512a5d891a35c1663392caryclark            }
70754359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("\n");
70807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
70907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
7104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while ((nextAngle = nextAngle->next()) != angle);
71154359294a7c9dc54802d512a5d891a35c1663392caryclark    start->segment()->markDone(start->starter(end));
71207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
71396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
71407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
71507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
71607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
71707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
71807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
71907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
72007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
72107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
72207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
72307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
72407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
72554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpanBase*>* chase,
72654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable) {
72754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* start = *nextStart;
72854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* end = *nextEnd;
72954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != end);
73054359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
73154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
73254359294a7c9dc54802d512a5d891a35c1663392caryclark    if (other) {
73307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // mark the smaller of startIndex, endIndex done, and all adjacent
73407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // spans with the same T value (but not 'other' spans)
73507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
73607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
73707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
73854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpan* startSpan = start->starter(end);
73954359294a7c9dc54802d512a5d891a35c1663392caryclark        if (startSpan->done()) {
74096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
741570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
74254359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(startSpan);
74354359294a7c9dc54802d512a5d891a35c1663392caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
74407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
74507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
74654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
74754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear == end);  // is this ever not end?
74854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear);
74954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != endNear);
75054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
7514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // more than one viable candidate -- measure angles to find best
75254359294a7c9dc54802d512a5d891a35c1663392caryclark    int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding);
753570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool sortable = calcWinding != SK_NaN32;
75407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!sortable) {
75507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *unsortable = true;
75654359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
75796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
75854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
75954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
76054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (angle->unorderable()) {
76154359294a7c9dc54802d512a5d891a35c1663392caryclark        *unsortable = true;
76254359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
76396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
76407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
7664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
7674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
76807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
76954359294a7c9dc54802d512a5d891a35c1663392caryclark    int sumWinding = updateWinding(end, start);
7704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
77196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpAngle* foundAngle = nullptr;
77207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
77354359294a7c9dc54802d512a5d891a35c1663392caryclark    // iterate through the angle, and compute everyone's winding
77407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
77507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
77607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
77707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
77807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
7794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                &sumWinding);
78007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (activeAngle) {
78107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++activeCount;
78207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (!foundAngle || (foundDone && activeCount & 1)) {
78307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundAngle = nextAngle;
78407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                foundDone = nextSegment->done(nextAngle);
78507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
78607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
78707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (nextSegment->done()) {
78807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            continue;
78907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
790570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (!activeAngle) {
79154359294a7c9dc54802d512a5d891a35c1663392caryclark            (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end());
792570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
79354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase* last = nextAngle->lastMarked();
79407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (last) {
7954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
79607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            *chase->append() = last;
79707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
79854359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__,
79954359294a7c9dc54802d512a5d891a35c1663392caryclark                    last->segment()->debugID(), last->debugID());
80054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!last->final()) {
80154359294a7c9dc54802d512a5d891a35c1663392caryclark                SkDebugf(" windSum=%d", last->upCast()->windSum());
80254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
80354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("\n");
80407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
80507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
8064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while ((nextAngle = nextAngle->next()) != angle);
80754359294a7c9dc54802d512a5d891a35c1663392caryclark    start->segment()->markDone(start->starter(end));
80807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
80996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
81007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
81107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
81207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
81307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
81407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
81507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
81607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
81707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
81807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
81907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
82007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
82154359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd,
82254359294a7c9dc54802d512a5d891a35c1663392caryclark        bool* unsortable) {
82354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* start = *nextStart;
82454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* end = *nextEnd;
82554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != end);
82654359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
82754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* other = this->isSimple(nextStart, &step);  // advances nextStart
82854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (other) {
82954359294a7c9dc54802d512a5d891a35c1663392caryclark    // mark the smaller of startIndex, endIndex done, and all adjacent
83054359294a7c9dc54802d512a5d891a35c1663392caryclark    // spans with the same T value (but not 'other' spans)
83107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
83207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s simple\n", __FUNCTION__);
83307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
83454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpan* startSpan = start->starter(end);
83554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (startSpan->done()) {
83696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
83707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
83854359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(startSpan);
83954359294a7c9dc54802d512a5d891a35c1663392caryclark        *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev();
84007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return other;
84107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
84254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \
84354359294a7c9dc54802d512a5d891a35c1663392caryclark            : (*nextStart)->prev());
84454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear == end);  // is this ever not end?
84554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endNear);
84654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != endNear);
84754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT((start->t() < endNear->t()) ^ (step < 0));
84854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpAngle* angle = this->spanToAngle(end, start);
84927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    if (!angle || angle->unorderable()) {
85054359294a7c9dc54802d512a5d891a35c1663392caryclark        *unsortable = true;
85154359294a7c9dc54802d512a5d891a35c1663392caryclark        markDone(start->starter(end));
85296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
85354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
8544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf("%s\n", __FUNCTION__);
8564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    angle->debugLoop();
857570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
8584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* nextAngle = angle->next();
85996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpAngle* foundAngle = nullptr;
86007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool foundDone = false;
86154359294a7c9dc54802d512a5d891a35c1663392caryclark    // iterate through the angle, and compute everyone's winding
86207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nextSegment;
86307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int activeCount = 0;
86407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    do {
86507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        nextSegment = nextAngle->segment();
86607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        ++activeCount;
86707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (!foundAngle || (foundDone && activeCount & 1)) {
86807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            foundAngle = nextAngle;
8694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (!(foundDone = nextSegment->done(nextAngle))) {
8704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                break;
8714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
87207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
8734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        nextAngle = nextAngle->next();
8744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } while (nextAngle != angle);
87554359294a7c9dc54802d512a5d891a35c1663392caryclark    start->segment()->markDone(start->starter(end));
87607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!foundAngle) {
87796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
87807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
87907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextStart = foundAngle->start();
88007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    *nextEnd = foundAngle->end();
88107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nextSegment = foundAngle->segment();
88207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
88307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
88407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd);
88507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif
88607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return nextSegment;
88707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
88807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
88954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpGlobalState* SkOpSegment::globalState() const {
89054359294a7c9dc54802d512a5d891a35c1663392caryclark    return contour()->globalState();
89165f553182ab7069378ef863d30094d0327f178d0caryclark}
89265f553182ab7069378ef863d30094d0327f178d0caryclark
8931049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkPath::Verb verb) {
89454359294a7c9dc54802d512a5d891a35c1663392caryclark    fContour = contour;
89596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fNext = nullptr;
89627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    fOriginal[0] = pts[0];
89727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    fOriginal[1] = pts[SkPathOpsVerbToPoints(verb)];
89807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPts = pts;
8991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    fWeight = weight;
90007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fVerb = verb;
90154359294a7c9dc54802d512a5d891a35c1663392caryclark    fCount = 0;
90254359294a7c9dc54802d512a5d891a35c1663392caryclark    fDoneCount = 0;
90354359294a7c9dc54802d512a5d891a35c1663392caryclark    fVisited = false;
90454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* zeroSpan = &fHead;
90596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    zeroSpan->init(this, nullptr, 0, fPts[0]);
90654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* oneSpan = &fTail;
90754359294a7c9dc54802d512a5d891a35c1663392caryclark    zeroSpan->setNext(oneSpan);
90854359294a7c9dc54802d512a5d891a35c1663392caryclark    oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]);
9091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(fID = globalState()->nextSegmentID());
91054359294a7c9dc54802d512a5d891a35c1663392caryclark}
91154359294a7c9dc54802d512a5d891a35c1663392caryclark
91254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::isClose(double t, const SkOpSegment* opp) const {
91354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDPoint cPt = this->dPtAtT(t);
9141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDVector dxdy = (*CurveDSlopeAtT[this->verb()])(this->pts(), this->weight(), t);
91554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
91654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkIntersections i;
9171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), perp, &i);
91854359294a7c9dc54802d512a5d891a35c1663392caryclark    int used = i.used();
91954359294a7c9dc54802d512a5d891a35c1663392caryclark    for (int index = 0; index < used; ++index) {
92054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (cPt.roughlyEqual(i.pt(index))) {
9210dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed            return true;
9220dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
92354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
924a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    return false;
925a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com}
926a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com
92754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::isXor() const {
92854359294a7c9dc54802d512a5d891a35c1663392caryclark    return fContour->isXor();
92907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
93007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9315b5ddd73b4baf22752924bf20d097e96236c36f8caryclarkvoid SkOpSegment::markAllDone() {
9325b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    SkOpSpan* span = this->head();
9335b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    do {
9345b5ddd73b4baf22752924bf20d097e96236c36f8caryclark        this->markDone(span);
9355b5ddd73b4baf22752924bf20d097e96236c36f8caryclark    } while ((span = span->next()->upCastable()));
9365b5ddd73b4baf22752924bf20d097e96236c36f8caryclark}
9375b5ddd73b4baf22752924bf20d097e96236c36f8caryclark
93854359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end) {
93954359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
94054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* minSpan = start->starter(end);
94154359294a7c9dc54802d512a5d891a35c1663392caryclark    markDone(minSpan);
94296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpanBase* last = nullptr;
94307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* other = this;
94454359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((other = other->nextChase(&start, &step, &minSpan, &last))) {
94507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (other->done()) {
946dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
947dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
94807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
94954359294a7c9dc54802d512a5d891a35c1663392caryclark        other->markDone(minSpan);
95007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
95107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
95207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
95307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
95454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding,
95554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase** lastPtr) {
95654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* spanStart = start->starter(end);
95754359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
95854359294a7c9dc54802d512a5d891a35c1663392caryclark    bool success = markWinding(spanStart, winding);
95996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpanBase* last = nullptr;
9604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpSegment* other = this;
96154359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
96254359294a7c9dc54802d512a5d891a35c1663392caryclark        if (spanStart->windSum() != SK_MinS32) {
96354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(spanStart->windSum() == winding);
964dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
965dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
9664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
96754359294a7c9dc54802d512a5d891a35c1663392caryclark        (void) other->markWinding(spanStart, winding);
9686f726addf3178b01949bb389ef83cf14a1d7b6b2caryclark    }
96965f553182ab7069378ef863d30094d0327f178d0caryclark    if (lastPtr) {
97065f553182ab7069378ef863d30094d0327f178d0caryclark        *lastPtr = last;
97165f553182ab7069378ef863d30094d0327f178d0caryclark    }
97265f553182ab7069378ef863d30094d0327f178d0caryclark    return success;
9734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
9744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
97554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end,
97654359294a7c9dc54802d512a5d891a35c1663392caryclark        int winding, int oppWinding, SkOpSpanBase** lastPtr) {
97754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* spanStart = start->starter(end);
97854359294a7c9dc54802d512a5d891a35c1663392caryclark    int step = start->step(end);
97954359294a7c9dc54802d512a5d891a35c1663392caryclark    bool success = markWinding(spanStart, winding, oppWinding);
98096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpanBase* last = nullptr;
98107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* other = this;
98254359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
98354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (spanStart->windSum() != SK_MinS32) {
98454359294a7c9dc54802d512a5d891a35c1663392caryclark            if (this->operand() == other->operand()) {
985624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark                if (spanStart->windSum() != winding || spanStart->oppSum() != oppWinding) {
98654359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->globalState()->setWindingFailed();
98754359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
988dac1d17027dcaa5596885a9f333979418b35001ccaryclark                }
98954359294a7c9dc54802d512a5d891a35c1663392caryclark            } else {
99054359294a7c9dc54802d512a5d891a35c1663392caryclark                SkASSERT(spanStart->windSum() == oppWinding);
99154359294a7c9dc54802d512a5d891a35c1663392caryclark                SkASSERT(spanStart->oppSum() == winding);
992dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
993dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!last);
994dac1d17027dcaa5596885a9f333979418b35001ccaryclark            break;
995dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
99654359294a7c9dc54802d512a5d891a35c1663392caryclark        if (this->operand() == other->operand()) {
99754359294a7c9dc54802d512a5d891a35c1663392caryclark            (void) other->markWinding(spanStart, winding, oppWinding);
998dac1d17027dcaa5596885a9f333979418b35001ccaryclark        } else {
99954359294a7c9dc54802d512a5d891a35c1663392caryclark            (void) other->markWinding(spanStart, oppWinding, winding);
100007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
100107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
100265f553182ab7069378ef863d30094d0327f178d0caryclark    if (lastPtr) {
100365f553182ab7069378ef863d30094d0327f178d0caryclark        *lastPtr = last;
100465f553182ab7069378ef863d30094d0327f178d0caryclark    }
100565f553182ab7069378ef863d30094d0327f178d0caryclark    return success;
100607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
100707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
100854359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) {
100907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(angle->segment() == this);
101007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (UseInnerWinding(maxWinding, sumWinding)) {
101107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        maxWinding = sumWinding;
101207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
101354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* last;
101454359294a7c9dc54802d512a5d891a35c1663392caryclark    (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, &last);
1015570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING
1016570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (last) {
101754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%s last seg=%d span=%d", __FUNCTION__,
101854359294a7c9dc54802d512a5d891a35c1663392caryclark                last->segment()->debugID(), last->debugID());
101954359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!last->final()) {
102054359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf(" windSum=");
102154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkPathOpsDebug::WindingPrintf(last->upCast()->windSum());
102254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
102354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
1024570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
1025570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
102607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
102707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
102807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
102954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding,
103054359294a7c9dc54802d512a5d891a35c1663392caryclark                                   int oppSumWinding, const SkOpAngle* angle) {
103107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkASSERT(angle->segment() == this);
103207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (UseInnerWinding(maxWinding, sumWinding)) {
103307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        maxWinding = sumWinding;
103407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
103507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) {
103607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        oppMaxWinding = oppSumWinding;
103707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
103896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpanBase* last = nullptr;
103965f553182ab7069378ef863d30094d0327f178d0caryclark    // caller doesn't require that this marks anything
104054359294a7c9dc54802d512a5d891a35c1663392caryclark    (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, &last);
1041570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING
1042570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (last) {
104354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%s last segment=%d span=%d", __FUNCTION__,
104454359294a7c9dc54802d512a5d891a35c1663392caryclark                last->segment()->debugID(), last->debugID());
104554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!last->final()) {
104654359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf(" windSum=");
104754359294a7c9dc54802d512a5d891a35c1663392caryclark            SkPathOpsDebug::WindingPrintf(last->upCast()->windSum());
104854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
104954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf(" \n");
1050570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
1051570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
105207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return last;
105307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
105407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
105554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::markDone(SkOpSpan* span) {
105654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this == span->segment());
105754359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->done()) {
10580dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        return;
10590dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
106054359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE
106154359294a7c9dc54802d512a5d891a35c1663392caryclark    debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum());
106254359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
106354359294a7c9dc54802d512a5d891a35c1663392caryclark    span->setDone(true);
106454359294a7c9dc54802d512a5d891a35c1663392caryclark    ++fDoneCount;
106554359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
10660dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed}
10670dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed
106854359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding) {
106954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this == span->segment());
107054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(winding);
107154359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->done()) {
107265f553182ab7069378ef863d30094d0327f178d0caryclark        return false;
107307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
107407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE
107554359294a7c9dc54802d512a5d891a35c1663392caryclark    debugShowNewWinding(__FUNCTION__, span, winding);
10760dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed#endif
107754359294a7c9dc54802d512a5d891a35c1663392caryclark    span->setWindSum(winding);
107854359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
107965f553182ab7069378ef863d30094d0327f178d0caryclark    return true;
108007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
108107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
108254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding, int oppWinding) {
108354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this == span->segment());
108454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(winding || oppWinding);
108554359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->done()) {
108665f553182ab7069378ef863d30094d0327f178d0caryclark        return false;
108707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
108807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE
108954359294a7c9dc54802d512a5d891a35c1663392caryclark    debugShowNewWinding(__FUNCTION__, span, winding, oppWinding);
10908cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif
109154359294a7c9dc54802d512a5d891a35c1663392caryclark    span->setWindSum(winding);
109254359294a7c9dc54802d512a5d891a35c1663392caryclark    span->setOppSum(oppWinding);
10934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    debugValidate();
109465f553182ab7069378ef863d30094d0327f178d0caryclark    return true;
109507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
109607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
109754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::match(const SkOpPtT* base, const SkOpSegment* testParent, double testT,
109854359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkPoint& testPt) const {
109954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSegment* baseParent = base->segment();
110054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (this == baseParent && this == testParent && precisely_equal(base->fT, testT)) {
110154359294a7c9dc54802d512a5d891a35c1663392caryclark        return true;
110207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
110354359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) {
110454359294a7c9dc54802d512a5d891a35c1663392caryclark        return false;
1105e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark    }
110608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    return !this->ptsDisjoint(base->fT, base->fPt, testT, testPt);
110754359294a7c9dc54802d512a5d891a35c1663392caryclark}
110854359294a7c9dc54802d512a5d891a35c1663392caryclark
110954359294a7c9dc54802d512a5d891a35c1663392caryclarkstatic SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) {
111054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (last) {
111154359294a7c9dc54802d512a5d891a35c1663392caryclark        *last = endSpan;
111207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
111396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
111407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
111507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
111654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr,
111754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase** last) const {
111854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* origStart = *startPtr;
1119dac1d17027dcaa5596885a9f333979418b35001ccaryclark    int step = *stepPtr;
112054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev();
112154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(endSpan);
112254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle();
112354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* foundSpan;
112454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* otherEnd;
1125dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpSegment* other;
112696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (angle == nullptr) {
112754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (endSpan->t() != 0 && endSpan->t() != 1) {
112896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
1129dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
113054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* otherPtT = endSpan->ptT()->next();
113154359294a7c9dc54802d512a5d891a35c1663392caryclark        other = otherPtT->segment();
113254359294a7c9dc54802d512a5d891a35c1663392caryclark        foundSpan = otherPtT->span();
113354359294a7c9dc54802d512a5d891a35c1663392caryclark        otherEnd = step > 0 ? foundSpan->upCast()->next() : foundSpan->prev();
1134dac1d17027dcaa5596885a9f333979418b35001ccaryclark    } else {
1135dac1d17027dcaa5596885a9f333979418b35001ccaryclark        int loopCount = angle->loopCount();
1136dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (loopCount > 2) {
113754359294a7c9dc54802d512a5d891a35c1663392caryclark            return set_last(last, endSpan);
1138dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
1139dac1d17027dcaa5596885a9f333979418b35001ccaryclark        const SkOpAngle* next = angle->next();
114096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == next) {
114196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
114265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark        }
1143dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING
1144624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (angle->debugSign() != next->debugSign() && !angle->segment()->contour()->isXor()
114554359294a7c9dc54802d512a5d891a35c1663392caryclark                && !next->segment()->contour()->isXor()) {
1146dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkDebugf("%s mismatched signs\n", __FUNCTION__);
11470dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
114854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
1149dac1d17027dcaa5596885a9f333979418b35001ccaryclark        other = next->segment();
115054359294a7c9dc54802d512a5d891a35c1663392caryclark        foundSpan = endSpan = next->start();
1151dac1d17027dcaa5596885a9f333979418b35001ccaryclark        otherEnd = next->end();
1152570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
115354359294a7c9dc54802d512a5d891a35c1663392caryclark    int foundStep = foundSpan->step(otherEnd);
1154dac1d17027dcaa5596885a9f333979418b35001ccaryclark    if (*stepPtr != foundStep) {
115554359294a7c9dc54802d512a5d891a35c1663392caryclark        return set_last(last, endSpan);
115607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
115754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(*startPtr);
115854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!otherEnd) {
115996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
116065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark    }
116165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark//    SkASSERT(otherEnd >= 0);
116254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast();
116354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* foundMin = foundSpan->starter(otherEnd);
116454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (foundMin->windValue() != origMin->windValue()
116554359294a7c9dc54802d512a5d891a35c1663392caryclark            || foundMin->oppValue() != origMin->oppValue()) {
116654359294a7c9dc54802d512a5d891a35c1663392caryclark          return set_last(last, endSpan);
1167dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
116854359294a7c9dc54802d512a5d891a35c1663392caryclark    *startPtr = foundSpan;
1169dac1d17027dcaa5596885a9f333979418b35001ccaryclark    *stepPtr = foundStep;
1170dac1d17027dcaa5596885a9f333979418b35001ccaryclark    if (minPtr) {
1171dac1d17027dcaa5596885a9f333979418b35001ccaryclark        *minPtr = foundMin;
1172a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
117307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return other;
117407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
117507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1176bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclarkstatic void clear_visited(SkOpSpanBase* span) {
117754359294a7c9dc54802d512a5d891a35c1663392caryclark    // reset visited flag back to false
117854359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
117954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
118054359294a7c9dc54802d512a5d891a35c1663392caryclark        while ((ptT = ptT->next()) != stopPtT) {
118154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSegment* opp = ptT->segment();
118254359294a7c9dc54802d512a5d891a35c1663392caryclark            opp->resetVisited();
118307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1184bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    } while (!span->final() && (span = span->upCast()->next()));
118507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
118607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
118754359294a7c9dc54802d512a5d891a35c1663392caryclark// look for pairs of undetected coincident curves
118854359294a7c9dc54802d512a5d891a35c1663392caryclark// assumes that segments going in have visited flag clear
118954359294a7c9dc54802d512a5d891a35c1663392caryclark// curve/curve intersection should now do a pretty good job of finding coincident runs so
119054359294a7c9dc54802d512a5d891a35c1663392caryclark// this may be only be necessary for line/curve pairs -- so skip unless this is a line and the
119154359294a7c9dc54802d512a5d891a35c1663392caryclark// the opp is not a line
119227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) {
119354359294a7c9dc54802d512a5d891a35c1663392caryclark    if (this->verb() != SkPath::kLine_Verb) {
119427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        return false;
119554359294a7c9dc54802d512a5d891a35c1663392caryclark    }
1196bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    if (this->done()) {
119727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        return false;
1198bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    }
119996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpSpan* prior = nullptr;
1200bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    SkOpSpanBase* spanBase = &fHead;
120154359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
1202bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
1203bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        SkASSERT(ptT->span() == spanBase);
120454359294a7c9dc54802d512a5d891a35c1663392caryclark        while ((ptT = ptT->next()) != spanStopPtT) {
1205182b499cd75c971f85cdf52c1827b3c220cc9011caryclark            if (ptT->deleted()) {
1206182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                continue;
1207182b499cd75c971f85cdf52c1827b3c220cc9011caryclark            }
120854359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSegment* opp = ptT->span()->segment();
120926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//            if (opp->verb() == SkPath::kLine_Verb) {
121026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//                continue;
121126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//            }
1212bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            if (opp->done()) {
121354359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
121454359294a7c9dc54802d512a5d891a35c1663392caryclark            }
1215bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
1216bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            if (!opp->visited()) {
121754359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
121854359294a7c9dc54802d512a5d891a35c1663392caryclark            }
1219bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            if (spanBase == &fHead) {
122054359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
1221bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            }
1222bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            SkOpSpan* span = spanBase->upCastable();
1223bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            // FIXME?: this assumes that if the opposite segment is coincident then no more
1224bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            // coincidence needs to be detected. This may not be true.
1225bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            if (span && span->containsCoincidence(opp)) {
122654359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
122754359294a7c9dc54802d512a5d891a35c1663392caryclark            }
122826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (spanBase->segment() == opp) {
122926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
123026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
1231bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            if (spanBase->containsCoinEnd(opp)) {
1232bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                continue;
1233bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            }
123496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkOpPtT* priorPtT = nullptr, * priorStopPtT;
123554359294a7c9dc54802d512a5d891a35c1663392caryclark            // find prior span containing opp segment
123696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkOpSegment* priorOpp = nullptr;
1237bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            SkOpSpan* priorTest = spanBase->prev();
1238bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            while (!priorOpp && priorTest) {
1239bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                priorStopPtT = priorPtT = priorTest->ptT();
124054359294a7c9dc54802d512a5d891a35c1663392caryclark                while ((priorPtT = priorPtT->next()) != priorStopPtT) {
1241182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                    if (priorPtT->deleted()) {
1242182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                        continue;
1243182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                    }
124454359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkOpSegment* segment = priorPtT->span()->segment();
124554359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (segment == opp) {
1246bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                        prior = priorTest;
124754359294a7c9dc54802d512a5d891a35c1663392caryclark                        priorOpp = opp;
124854359294a7c9dc54802d512a5d891a35c1663392caryclark                        break;
124954359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
125054359294a7c9dc54802d512a5d891a35c1663392caryclark                }
1251bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                priorTest = priorTest->prev();
125254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
125354359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!priorOpp) {
125454359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
125554359294a7c9dc54802d512a5d891a35c1663392caryclark            }
125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (priorPtT == ptT) {
125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
125954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpPtT* oppStart = prior->ptT();
1260bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark            SkOpPtT* oppEnd = spanBase->ptT();
126154359294a7c9dc54802d512a5d891a35c1663392caryclark            bool swapped = priorPtT->fT > ptT->fT;
126254359294a7c9dc54802d512a5d891a35c1663392caryclark            if (swapped) {
126354359294a7c9dc54802d512a5d891a35c1663392caryclark                SkTSwap(priorPtT, ptT);
126454359294a7c9dc54802d512a5d891a35c1663392caryclark                SkTSwap(oppStart, oppEnd);
126554359294a7c9dc54802d512a5d891a35c1663392caryclark            }
126654359294a7c9dc54802d512a5d891a35c1663392caryclark            bool flipped = oppStart->fT > oppEnd->fT;
126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool coincident = false;
126854359294a7c9dc54802d512a5d891a35c1663392caryclark            if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) {
126954359294a7c9dc54802d512a5d891a35c1663392caryclark                goto swapBack;
127054359294a7c9dc54802d512a5d891a35c1663392caryclark            }
127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (opp->verb() == SkPath::kLine_Verb) {
127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppStart->fPt) ||
127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt)) &&
127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) ||
127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt));
127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!coincident) {
127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000);
127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
128054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (coincident) {
128154359294a7c9dc54802d512a5d891a35c1663392caryclark            // mark coincidence
1282182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd)
1283182b499cd75c971f85cdf52c1827b3c220cc9011caryclark                        && !coincidences->extend(oppStart, oppEnd, priorPtT, ptT)) {
1284bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                    coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator);
1285bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark                }
128654359294a7c9dc54802d512a5d891a35c1663392caryclark                clear_visited(&fHead);
128727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                return true;
128854359294a7c9dc54802d512a5d891a35c1663392caryclark            }
128954359294a7c9dc54802d512a5d891a35c1663392caryclark    swapBack:
129054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (swapped) {
129154359294a7c9dc54802d512a5d891a35c1663392caryclark                SkTSwap(priorPtT, ptT);
129254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
12930dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed        }
129496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next()));
129554359294a7c9dc54802d512a5d891a35c1663392caryclark    clear_visited(&fHead);
129627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return false;
129754359294a7c9dc54802d512a5d891a35c1663392caryclark}
129854359294a7c9dc54802d512a5d891a35c1663392caryclark
129908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark// if a span has more than one intersection, merge the other segments' span as needed
1300d78c088b6136590371fddd4cab67bfb4bf692fd3caryclarkbool SkOpSegment::moveMultiples() {
130108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    debugValidate();
130208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    SkOpSpanBase* test = &fHead;
130308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    do {
130408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        int addCount = test->spanAddsCount();
1305d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark        if (addCount < 1) {
1306d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark            return false;
1307d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark        }
130808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        if (addCount == 1) {
130908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            continue;
131008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        }
131108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        SkOpPtT* startPtT = test->ptT();
131208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        SkOpPtT* testPtT = startPtT;
131308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        do {  // iterate through all spans associated with start
131408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppSpan = testPtT->span();
131508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            if (oppSpan->spanAddsCount() == addCount) {
131608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                continue;
131708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
131808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            if (oppSpan->deleted()) {
131908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                continue;
132008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
132108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSegment* oppSegment = oppSpan->segment();
132208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            if (oppSegment == this) {
132308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                continue;
132408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
132508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            // find range of spans to consider merging
132608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppPrev = oppSpan;
132708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppFirst = oppSpan;
132808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            while ((oppPrev = oppPrev->prev())) {
132908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (!roughly_equal(oppPrev->t(), oppSpan->t())) {
133008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    break;
133108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
133208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (oppPrev->spanAddsCount() == addCount) {
133308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    continue;
133408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
133508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (oppPrev->deleted()) {
133608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    continue;
133708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
133808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                oppFirst = oppPrev;
133908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
134008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppNext = oppSpan;
134108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppLast = oppSpan;
134296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) {
134308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (!roughly_equal(oppNext->t(), oppSpan->t())) {
134408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    break;
134508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
134608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (oppNext->spanAddsCount() == addCount) {
134708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    continue;
134808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
134908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (oppNext->deleted()) {
135008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    continue;
135108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
135208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                oppLast = oppNext;
135308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
135408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            if (oppFirst == oppLast) {
135508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                continue;
135608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            }
135708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            SkOpSpanBase* oppTest = oppFirst;
135808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            do {
135908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                if (oppTest == oppSpan) {
136008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    continue;
136108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
136208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                // check to see if the candidate meets specific criteria:
136308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                // it contains spans of segments in test's loop but not including 'this'
136408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                SkOpPtT* oppStartPtT = oppTest->ptT();
136508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                SkOpPtT* oppPtT = oppStartPtT;
136608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                while ((oppPtT = oppPtT->next()) != oppStartPtT) {
136708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    SkOpSegment* oppPtTSegment = oppPtT->segment();
136808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    if (oppPtTSegment == this) {
136908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        goto tryNextSpan;
137008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    }
137108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    SkOpPtT* matchPtT = startPtT;
137208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    do {
137308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        if (matchPtT->segment() == oppPtTSegment) {
137408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                            goto foundMatch;
137508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        }
137608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    } while ((matchPtT = matchPtT->next()) != startPtT);
137708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    goto tryNextSpan;
137808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            foundMatch:  // merge oppTest and oppSpan
137908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    oppSegment->debugValidate();
138008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) {
138108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse
138208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        SkASSERT(oppSpan != &oppSegment->fTail);
138308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        oppTest->merge(oppSpan->upCast());
138408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    } else {
138508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                        oppSpan->merge(oppTest->upCast());
138608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    }
138708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    oppSegment->debugValidate();
138808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                    goto checkNextSpan;
138908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                }
139008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        tryNextSpan:
139108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                ;
139208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark            } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()));
139308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        } while ((testPtT = testPtT->next()) != startPtT);
139408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclarkcheckNextSpan:
139508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark        ;
139696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    } while ((test = test->final() ? nullptr : test->upCast()->next()));
139708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    debugValidate();
1398d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark    return true;
139908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark}
140008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark
140154359294a7c9dc54802d512a5d891a35c1663392caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later.
140208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclarkvoid SkOpSegment::moveNearby() {
140354359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
140454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* spanS = &fHead;
140554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
140654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase* test = spanS->upCast()->next();
140754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSpanBase* next;
140854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (spanS->contains(test)) {
140954359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!test->final()) {
141054359294a7c9dc54802d512a5d891a35c1663392caryclark                test->upCast()->detach(spanS->ptT());
141154359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
141254359294a7c9dc54802d512a5d891a35c1663392caryclark            } else if (spanS != &fHead) {
141354359294a7c9dc54802d512a5d891a35c1663392caryclark                spanS->upCast()->detach(test->ptT());
141454359294a7c9dc54802d512a5d891a35c1663392caryclark                spanS = test;
1415570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                continue;
1416570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            }
141707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
141854359294a7c9dc54802d512a5d891a35c1663392caryclark        do {  // iterate through all spans associated with start
141954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpPtT* startBase = spanS->ptT();
142096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            next = test->final() ? nullptr : test->upCast()->next();
142154359294a7c9dc54802d512a5d891a35c1663392caryclark            do {
142254359294a7c9dc54802d512a5d891a35c1663392caryclark                SkOpPtT* testBase = test->ptT();
142354359294a7c9dc54802d512a5d891a35c1663392caryclark                do {
142454359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (startBase == testBase) {
142554359294a7c9dc54802d512a5d891a35c1663392caryclark                        goto checkNextSpan;
142654359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
142754359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (testBase->duplicate()) {
142854359294a7c9dc54802d512a5d891a35c1663392caryclark                        continue;
142954359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
143054359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) {
143154359294a7c9dc54802d512a5d891a35c1663392caryclark                        if (test == &this->fTail) {
143254359294a7c9dc54802d512a5d891a35c1663392caryclark                            if (spanS == &fHead) {
143354359294a7c9dc54802d512a5d891a35c1663392caryclark                                debugValidate();
143408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                                return;  // if this span has collapsed, remove it from parent
143554359294a7c9dc54802d512a5d891a35c1663392caryclark                            }
143654359294a7c9dc54802d512a5d891a35c1663392caryclark                            this->fTail.merge(spanS->upCast());
143754359294a7c9dc54802d512a5d891a35c1663392caryclark                            debugValidate();
143808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark                            return;
143954359294a7c9dc54802d512a5d891a35c1663392caryclark                        }
144054359294a7c9dc54802d512a5d891a35c1663392caryclark                        spanS->merge(test->upCast());
144154359294a7c9dc54802d512a5d891a35c1663392caryclark                        goto checkNextSpan;
144254359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
144354359294a7c9dc54802d512a5d891a35c1663392caryclark                } while ((testBase = testBase->next()) != test->ptT());
144454359294a7c9dc54802d512a5d891a35c1663392caryclark            } while ((startBase = startBase->next()) != spanS->ptT());
144554359294a7c9dc54802d512a5d891a35c1663392caryclark    checkNextSpan:
144654359294a7c9dc54802d512a5d891a35c1663392caryclark            ;
144754359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((test = next));
144854359294a7c9dc54802d512a5d891a35c1663392caryclark        spanS = spanS->upCast()->next();
144954359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (!spanS->final());
145054359294a7c9dc54802d512a5d891a35c1663392caryclark    debugValidate();
1451dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
1452dac1d17027dcaa5596885a9f333979418b35001ccaryclark
145354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::operand() const {
145454359294a7c9dc54802d512a5d891a35c1663392caryclark    return fContour->operand();
14555e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark}
14565e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark
145754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::oppXor() const {
145854359294a7c9dc54802d512a5d891a35c1663392caryclark    return fContour->oppXor();
1459ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1460ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
146154359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const {
146254359294a7c9dc54802d512a5d891a35c1663392caryclark    if (fVerb == SkPath::kLine_Verb) {
146354359294a7c9dc54802d512a5d891a35c1663392caryclark        return false;
14640dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed    }
146554359294a7c9dc54802d512a5d891a35c1663392caryclark    // quads (and cubics) can loop back to nearly a line so that an opposite curve
146654359294a7c9dc54802d512a5d891a35c1663392caryclark    // hits in two places with very different t values.
146754359294a7c9dc54802d512a5d891a35c1663392caryclark    // OPTIMIZATION: curves could be preflighted so that, for example, something like
146854359294a7c9dc54802d512a5d891a35c1663392caryclark    // 'controls contained by ends' could avoid this check for common curves
146954359294a7c9dc54802d512a5d891a35c1663392caryclark    // 'ends are extremes in x or y' is cheaper to compute and real-world common
147054359294a7c9dc54802d512a5d891a35c1663392caryclark    // on the other hand, the below check is relatively inexpensive
147154359294a7c9dc54802d512a5d891a35c1663392caryclark    double midT = (t1 + t2) / 2;
147254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkPoint midPt = this->ptAtT(midT);
147354359294a7c9dc54802d512a5d891a35c1663392caryclark    double seDistSq = SkTMax(pt1.distanceToSqd(pt2) * 2, FLT_EPSILON * 2);
147454359294a7c9dc54802d512a5d891a35c1663392caryclark    return midPt.distanceToSqd(pt1) > seDistSq || midPt.distanceToSqd(pt2) > seDistSq;
147554359294a7c9dc54802d512a5d891a35c1663392caryclark}
147654359294a7c9dc54802d512a5d891a35c1663392caryclark
147754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding,
147854359294a7c9dc54802d512a5d891a35c1663392caryclark        int* maxWinding, int* sumWinding) {
147954359294a7c9dc54802d512a5d891a35c1663392caryclark    int deltaSum = SpanSign(start, end);
148054359294a7c9dc54802d512a5d891a35c1663392caryclark    *maxWinding = *sumMiWinding;
148154359294a7c9dc54802d512a5d891a35c1663392caryclark    *sumWinding = *sumMiWinding -= deltaSum;
148260e0fee6d4acff638ccc9670c4055aced529a7a0bungeman    SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
1483dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
1484dac1d17027dcaa5596885a9f333979418b35001ccaryclark
148554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding,
148654359294a7c9dc54802d512a5d891a35c1663392caryclark        int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding,
148754359294a7c9dc54802d512a5d891a35c1663392caryclark        int* oppSumWinding) {
148854359294a7c9dc54802d512a5d891a35c1663392caryclark    int deltaSum = SpanSign(start, end);
148954359294a7c9dc54802d512a5d891a35c1663392caryclark    int oppDeltaSum = OppSign(start, end);
149007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (operand()) {
149107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *maxWinding = *sumSuWinding;
149207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *sumWinding = *sumSuWinding -= deltaSum;
149307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppMaxWinding = *sumMiWinding;
149407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppSumWinding = *sumMiWinding -= oppDeltaSum;
149507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
149607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *maxWinding = *sumMiWinding;
149707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *sumWinding = *sumMiWinding -= deltaSum;
149807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppMaxWinding = *sumSuWinding;
149907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *oppSumWinding = *sumSuWinding -= oppDeltaSum;
150007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
150160e0fee6d4acff638ccc9670c4055aced529a7a0bungeman    SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
150260e0fee6d4acff638ccc9670c4055aced529a7a0bungeman    SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM);
150307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
150407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::sortAngles() {
150654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* span = &this->fHead;
15074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    do {
150854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpAngle* fromAngle = span->fromAngle();
150996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkOpAngle* toAngle = span->final() ? nullptr : span->upCast()->toAngle();
1510dac1d17027dcaa5596885a9f333979418b35001ccaryclark        if (!fromAngle && !toAngle) {
15114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
15124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1513cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#if DEBUG_ANGLE
15144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        bool wroteAfterHeader = false;
1515cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#endif
151654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpAngle* baseAngle = fromAngle;
151754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (fromAngle && toAngle) {
15184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE
151954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(),
152054359294a7c9dc54802d512a5d891a35c1663392caryclark                    span->debugID());
152154359294a7c9dc54802d512a5d891a35c1663392caryclark            wroteAfterHeader = true;
15224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
152354359294a7c9dc54802d512a5d891a35c1663392caryclark            fromAngle->insert(toAngle);
152454359294a7c9dc54802d512a5d891a35c1663392caryclark        } else if (!fromAngle) {
152554359294a7c9dc54802d512a5d891a35c1663392caryclark            baseAngle = toAngle;
152607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
152754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
15284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        do {
152954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSpanBase* oSpan = ptT->span();
153054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (oSpan == span) {
153154359294a7c9dc54802d512a5d891a35c1663392caryclark                continue;
153254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
153354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpAngle* oAngle = oSpan->fromAngle();
1534dac1d17027dcaa5596885a9f333979418b35001ccaryclark            if (oAngle) {
1535570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_ANGLE
15364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                if (!wroteAfterHeader) {
153754359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
153854359294a7c9dc54802d512a5d891a35c1663392caryclark                            span->t(), span->debugID());
15394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                    wroteAfterHeader = true;
15404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                }
1541570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif
154254359294a7c9dc54802d512a5d891a35c1663392caryclark                if (!oAngle->loopContains(baseAngle)) {
15438cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                    baseAngle->insert(oAngle);
15448cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                }
15454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
154654359294a7c9dc54802d512a5d891a35c1663392caryclark            if (!oSpan->final()) {
154754359294a7c9dc54802d512a5d891a35c1663392caryclark                oAngle = oSpan->upCast()->toAngle();
154854359294a7c9dc54802d512a5d891a35c1663392caryclark                if (oAngle) {
15494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE
155054359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (!wroteAfterHeader) {
155154359294a7c9dc54802d512a5d891a35c1663392caryclark                        SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(),
155254359294a7c9dc54802d512a5d891a35c1663392caryclark                                span->t(), span->debugID());
155354359294a7c9dc54802d512a5d891a35c1663392caryclark                        wroteAfterHeader = true;
155454359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
15554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
155654359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (!oAngle->loopContains(baseAngle)) {
155754359294a7c9dc54802d512a5d891a35c1663392caryclark                        baseAngle->insert(oAngle);
155854359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
15598cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                }
15604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
156154359294a7c9dc54802d512a5d891a35c1663392caryclark        } while ((ptT = ptT->next()) != stopPtT);
156254359294a7c9dc54802d512a5d891a35c1663392caryclark        if (baseAngle->loopCount() == 1) {
156396fcdcc219d2a0d3579719b84b28bede76efba64halcanary            span->setFromAngle(nullptr);
156454359294a7c9dc54802d512a5d891a35c1663392caryclark            if (toAngle) {
156596fcdcc219d2a0d3579719b84b28bede76efba64halcanary                span->upCast()->setToAngle(nullptr);
15664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
156796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            baseAngle = nullptr;
15684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
15694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT
15704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
15714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
157254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (!span->final() && (span = span->upCast()->next()));
1573570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1574570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1575cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed
157654359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end,
15771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkOpCurve* edge) const {
1578cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    SkASSERT(start != end);
157954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT& startPtT = *start->ptT();
158054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT& endPtT = *end->ptT();
15811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(edge->fVerb = fVerb);
15821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    edge->fPts[0] = startPtT.fPt;
1583cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    int points = SkPathOpsVerbToPoints(fVerb);
15841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    edge->fPts[points] = endPtT.fPt;
15851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    edge->fWeight = 1;
1586cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kLine_Verb) {
1587cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1588cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
158954359294a7c9dc54802d512a5d891a35c1663392caryclark    double startT = startPtT.fT;
159054359294a7c9dc54802d512a5d891a35c1663392caryclark    double endT = endPtT.fT;
1591cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) {
1592cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        // don't compute midpoints if we already have them
159307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (fVerb == SkPath::kQuad_Verb) {
15941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fPts[1] = fPts[1];
15951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            return false;
15961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
15971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (fVerb == SkPath::kConic_Verb) {
15981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fPts[1] = fPts[1];
15991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fWeight = fWeight;
1600cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
160107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1602cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1603cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        if (start < end) {
16041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fPts[1] = fPts[1];
16051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fPts[2] = fPts[2];
1606cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1607cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
16081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[1] = fPts[2];
16091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[2] = fPts[1];
1610cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1611cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
16121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    const SkDPoint sub[2] = {{ edge->fPts[0].fX, edge->fPts[0].fY},
16131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            {edge->fPts[points].fX, edge->fPts[points].fY }};
1614cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kQuad_Verb) {
16151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoint();
16161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    } else if (fVerb == SkPath::kConic_Verb) {
16171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[1] = SkDConic::SubDivide(fPts, fWeight, sub[0], sub[1],
16181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                startT, endT, &edge->fWeight).asSkPoint();
1619cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    } else {
1620cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
1621cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDPoint ctrl[2];
1622cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl);
16231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[1] = ctrl[0].asSkPoint();
16241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fPts[2] = ctrl[1].asSkPoint();
162507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
1626cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    return true;
1627cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com}
1628cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
162954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end,
16301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDCurve* edge) const {
1631cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    SkASSERT(start != end);
163254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT& startPtT = *start->ptT();
163354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT& endPtT = *end->ptT();
16341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(edge->fVerb = fVerb);
16351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    edge->fCubic[0].set(startPtT.fPt);
1636cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    int points = SkPathOpsVerbToPoints(fVerb);
16371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    edge->fCubic[points].set(endPtT.fPt);
1638cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kLine_Verb) {
1639cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1640cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
164154359294a7c9dc54802d512a5d891a35c1663392caryclark    double startT = startPtT.fT;
164254359294a7c9dc54802d512a5d891a35c1663392caryclark    double endT = endPtT.fT;
1643cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) {
1644cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        // don't compute midpoints if we already have them
1645cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        if (fVerb == SkPath::kQuad_Verb) {
16461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fLine[1].set(fPts[1]);
16471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            return false;
16481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
16491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (fVerb == SkPath::kConic_Verb) {
16501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fConic[1].set(fPts[1]);
16511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fConic.fWeight = fWeight;
1652cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1653cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
1654cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
165554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (startT == 0) {
16561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fCubic[1].set(fPts[1]);
16571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            edge->fCubic[2].set(fPts[2]);
1658cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com            return false;
1659cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        }
16601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fCubic[1].set(fPts[2]);
16611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fCubic[2].set(fPts[1]);
1662cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return false;
1663cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1664cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    if (fVerb == SkPath::kQuad_Verb) {
16651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fQuad[1] = SkDQuad::SubDivide(fPts, edge->fQuad[0], edge->fQuad[2], startT, endT);
16661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    } else if (fVerb == SkPath::kConic_Verb) {
16671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        edge->fConic[1] = SkDConic::SubDivide(fPts, fWeight, edge->fQuad[0], edge->fQuad[2],
16681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            startT, endT, &edge->fConic.fWeight);
1669cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    } else {
1670cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkASSERT(fVerb == SkPath::kCubic_Verb);
16711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT, &edge->fCubic[1]);
1672cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1673cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    return true;
167407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
167507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
167627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpSegment::testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT,
167727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        const SkOpSpanBase* prior, const SkOpSpanBase* spanBase, const SkOpSegment* opp,
167827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkScalar flatnessLimit) const {
167927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    // average t, find mid pt
168027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    double midT = (prior->t() + spanBase->t()) / 2;
168127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    SkPoint midPt = this->ptAtT(midT);
168227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    bool coincident = true;
168327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    // if the mid pt is not near either end pt, project perpendicular through opp seg
168427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt)
168527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) {
168627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        coincident = false;
168727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkIntersections i;
168827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        SkVector dxdy = (*CurveSlopeAtT[fVerb])(this->pts(), this->weight(), midT);
1689b669300a9753893ef900207c38aeff2d467764e5caryclark        SkDLine ray = {{{midPt.fX, midPt.fY},
1690b669300a9753893ef900207c38aeff2d467764e5caryclark                {(double) midPt.fX + dxdy.fY, (double) midPt.fY - dxdy.fX}}};
169127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), ray, &i);
169227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        // measure distance and see if it's small enough to denote coincidence
169327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        for (int index = 0; index < i.used(); ++index) {
169427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            SkDPoint oppPt = i.pt(index);
169527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            if (oppPt.approximatelyEqual(midPt)) {
169627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkVector oppDxdy = (*CurveSlopeAtT[opp->verb()])(opp->pts(),
169727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                        opp->weight(), i[index][0]);
169827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                oppDxdy.normalize();
169927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                dxdy.normalize();
170027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy) / FLT_EPSILON);
170127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark                coincident |= flatness < flatnessLimit;
170227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark            }
170327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark        }
170427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    }
170527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return coincident;
170627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark}
170727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
170854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) {
170954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* span = this->head();
171054359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
171154359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!span->done()) {
171207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            break;
171307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
171454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((span = span->next()->upCastable()));
171554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(span);
171654359294a7c9dc54802d512a5d891a35c1663392caryclark    *start = span;
171754359294a7c9dc54802d512a5d891a35c1663392caryclark    *end = span->next();
171807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
171907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
172054359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const {
172154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* lesser = start->starter(end);
172254359294a7c9dc54802d512a5d891a35c1663392caryclark    int oppWinding = lesser->oppSum();
172354359294a7c9dc54802d512a5d891a35c1663392caryclark    int oppSpanWinding = SkOpSegment::OppSign(start, end);
172407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding)
172507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            && oppWinding != SK_MaxS32) {
172607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        oppWinding -= oppSpanWinding;
172707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
172807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return oppWinding;
172907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
173007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
173107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(const SkOpAngle* angle) const {
173254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* startSpan = angle->start();
173354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* endSpan = angle->end();
173454359294a7c9dc54802d512a5d891a35c1663392caryclark    return updateOppWinding(endSpan, startSpan);
173507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
173607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
173707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const {
173854359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* startSpan = angle->start();
173954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* endSpan = angle->end();
174054359294a7c9dc54802d512a5d891a35c1663392caryclark    return updateOppWinding(startSpan, endSpan);
174107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
174207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1743624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) {
1744624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpan* lesser = start->starter(end);
174554359294a7c9dc54802d512a5d891a35c1663392caryclark    int winding = lesser->windSum();
17468cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    if (winding == SK_MinS32) {
1747bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        winding = lesser->computeWindSum();
1748624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
1749624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    if (winding == SK_MinS32) {
17508cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org        return winding;
17518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    }
175254359294a7c9dc54802d512a5d891a35c1663392caryclark    int spanWinding = SkOpSegment::SpanSign(start, end);
1753570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    if (winding && UseInnerWinding(winding - spanWinding, winding)
1754570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            && winding != SK_MaxS32) {
175507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        winding -= spanWinding;
175607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
175707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return winding;
175807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
175907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1760624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWinding(SkOpAngle* angle) {
1761624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpanBase* startSpan = angle->start();
1762624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpanBase* endSpan = angle->end();
176354359294a7c9dc54802d512a5d891a35c1663392caryclark    return updateWinding(endSpan, startSpan);
1764570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1765570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1766624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWindingReverse(const SkOpAngle* angle) {
1767624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpanBase* startSpan = angle->start();
1768624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkOpSpanBase* endSpan = angle->end();
176954359294a7c9dc54802d512a5d891a35c1663392caryclark    return updateWinding(startSpan, endSpan);
1770570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1771570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1772570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// OPTIMIZATION: does the following also work, and is it any faster?
1773570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// return outerWinding * innerWinding > 0
1774570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com//      || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
1775570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) {
1776570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkASSERT(outerWinding != SK_MaxS32);
1777570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkASSERT(innerWinding != SK_MaxS32);
177860e0fee6d4acff638ccc9670c4055aced529a7a0bungeman    int absOut = SkTAbs(outerWinding);
177960e0fee6d4acff638ccc9670c4055aced529a7a0bungeman    int absIn = SkTAbs(innerWinding);
1780570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
1781570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    return result;
1782570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
1783570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
178407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windSum(const SkOpAngle* angle) const {
178554359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* minSpan = angle->start()->starter(angle->end());
178654359294a7c9dc54802d512a5d891a35c1663392caryclark    return minSpan->windSum();
178707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
1788