SkPathOpsDebug.cpp revision d6562000efca50bc2bfddae8dcb69dce6b8c0950
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 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 */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h"
926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h"
1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h"
1102802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h"
121b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h"
1354359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h"
1454359294a7c9dc54802d512a5d891a35c1663392caryclark
1555888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans;
1626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
1754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
1854359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail;
1954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
21624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
22624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
23624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount;
24624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
25624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
26624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP
27624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
28624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
29624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
32570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org
34fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0;
35fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0;
36570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
3754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray,
3854359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* span) {
394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int index = 0; index < chaseArray.count(); ++index) {
4054359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* entry = chaseArray[index];
414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (entry == span) {
424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return true;
434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return false;
464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
4726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
4826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
4955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
5026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkenum GlitchType {
5126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddCorruptCoin_Glitch,
5226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddExpandedCoin_Glitch,
5355888e44171ffd48b591d19256884a969fe4da17caryclark    kAddExpandedFail_Glitch,
5455888e44171ffd48b591d19256884a969fe4da17caryclark    kAddIfMissingCoin_Glitch,
5526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddMissingCoin_Glitch,
5655888e44171ffd48b591d19256884a969fe4da17caryclark    kAddMissingExtend_Glitch,
5755888e44171ffd48b591d19256884a969fe4da17caryclark    kAddOrOverlap_Glitch,
5826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedCoin_Glitch,
5926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedDone_Glitch,
6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedOppValue_Glitch,
6126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedSpan_Glitch,
6226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedWindValue_Glitch,
6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kDeletedCoin_Glitch,
6426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kExpandCoin_Glitch,
6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMarkCoinEnd_Glitch,
6626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMarkCoinInsert_Glitch,
6755888e44171ffd48b591d19256884a969fe4da17caryclark    kMarkCoinMissing_Glitch,
6855888e44171ffd48b591d19256884a969fe4da17caryclark    kMarkCoinStart_Glitch,
6955888e44171ffd48b591d19256884a969fe4da17caryclark    kMergeContained_Glitch,
7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingCoin_Glitch,
7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingDone_Glitch,
7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingIntersection_Glitch,
7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMoveMultiple_Glitch,
7455888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyClearAll_Glitch,
7555888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyClearAll2_Glitch,
7655888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyMerge_Glitch,
7755888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyMergeFinal_Glitch,
7855888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyRelease_Glitch,
7955888e44171ffd48b591d19256884a969fe4da17caryclark    kMoveNearbyReleaseFinal_Glitch,
8055888e44171ffd48b591d19256884a969fe4da17caryclark    kReleasedSpan_Glitch,
8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnaligned_Glitch,
8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnalignedHead_Glitch,
8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnalignedTail_Glitch,
8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
8655888e44171ffd48b591d19256884a969fe4da17caryclarkstatic const int kGlitchType_Count = kUnalignedTail_Glitch + 1;
8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
8826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch {
8926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* fStage;
9026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fBase;
9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fSuspect;
9226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* fSegment;
9355888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* fOppSegment;
9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fCoinSpan;
9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fEndSpan;
9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppSpan;
9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppEndSpan;
9855888e44171ffd48b591d19256884a969fe4da17caryclark    double fStartT;
9955888e44171ffd48b591d19256884a969fe4da17caryclark    double fEndT;
10055888e44171ffd48b591d19256884a969fe4da17caryclark    double fOppStartT;
10155888e44171ffd48b591d19256884a969fe4da17caryclark    double fOppEndT;
10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkPoint fPt;
10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    GlitchType fType;
10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog {
10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SpanGlitch* recordCommon(GlitchType type, const char* stage) {
10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = fGlitches.push();
10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fStage = stage;
11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = nullptr;
11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = nullptr;
11226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = nullptr;
11355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSegment = nullptr;
11426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = nullptr;
11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = nullptr;
11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = nullptr;
11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = nullptr;
11855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = SK_ScalarNaN;
11955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndT = SK_ScalarNaN;
12055888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppStartT = SK_ScalarNaN;
12155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndT = SK_ScalarNaN;
12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN };
12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fType = type;
12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return glitch;
12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base,
12826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* suspect = NULL) {
12926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
13026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
13126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = suspect;
13226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
13326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
13455888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base,
13555888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* ptT) {
13655888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
13755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = base;
13855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = ptT;
13955888e44171ffd48b591d19256884a969fe4da17caryclark    }
14055888e44171ffd48b591d19256884a969fe4da17caryclark
14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
14255888e44171ffd48b591d19256884a969fe4da17caryclark            const SkCoincidentSpans* opp = NULL) {
14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
14455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
14555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
14655888e44171ffd48b591d19256884a969fe4da17caryclark        if (opp) {
14755888e44171ffd48b591d19256884a969fe4da17caryclark            glitch->fOppSpan = opp->coinPtTStart();
14855888e44171ffd48b591d19256884a969fe4da17caryclark            glitch->fOppEndSpan = opp->coinPtTEnd();
14955888e44171ffd48b591d19256884a969fe4da17caryclark        }
15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
15126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base,
15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* seg, double t, SkPoint pt) {
15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
15526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = seg;
15755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
15926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base, double t,
16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkPoint pt) {
16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
16555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
16626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
16926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
17026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* coinSpan, const SkOpPtT* endSpan) {
17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
17255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
17355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
17426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = endSpan;
17555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSpan = coinSpan;
17655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndSpan = endSpan;
17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
18055888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpanBase* base) {
18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
18255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = base;
18355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
18455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const SkOpPtT* ptTE,
18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) {
18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = ptTS;
19126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = ptTE;
19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = oPtTS;
19326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = oPtTE;
19426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
19526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
19655888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, const SkOpSegment* seg, double startT,
19755888e44171ffd48b591d19256884a969fe4da17caryclark            double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) {
19855888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
19955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
20055888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = startT;
20155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndT = endT;
20255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSegment = oppSeg;
20355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppStartT = oppStartT;
20455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndT = oppEndT;
20555888e44171ffd48b591d19256884a969fe4da17caryclark    }
20655888e44171ffd48b591d19256884a969fe4da17caryclark
20755888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, const SkOpSegment* seg,
20855888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpan* span) {
20955888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
21055888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
21155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = span;
21255888e44171ffd48b591d19256884a969fe4da17caryclark    }
21355888e44171ffd48b591d19256884a969fe4da17caryclark
21455888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, double t, const SkOpSpanBase* span) {
21555888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
21655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
21755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = span;
21855888e44171ffd48b591d19256884a969fe4da17caryclark    }
21955888e44171ffd48b591d19256884a969fe4da17caryclark
22055888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, const SkOpSegment* seg) {
22155888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
22255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
22355888e44171ffd48b591d19256884a969fe4da17caryclark    }
22455888e44171ffd48b591d19256884a969fe4da17caryclark
22555888e44171ffd48b591d19256884a969fe4da17caryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
22655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* ptT) {
22755888e44171ffd48b591d19256884a969fe4da17caryclark        SpanGlitch* glitch = recordCommon(type, stage);
22855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
22955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = ptT;
23055888e44171ffd48b591d19256884a969fe4da17caryclark    }
23155888e44171ffd48b591d19256884a969fe4da17caryclark
23226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkTDArray<SpanGlitch> fGlitches;
23326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
23455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
23526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
23655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) {
23755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS
23855888e44171ffd48b591d19256884a969fe4da17caryclark    SkOpContour* contour = contourList;
23955888e44171ffd48b591d19256884a969fe4da17caryclark    do {
24055888e44171ffd48b591d19256884a969fe4da17caryclark        contour->debugShowActiveSpans();
24155888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((contour = contour->next()));
24255888e44171ffd48b591d19256884a969fe4da17caryclark#endif
24355888e44171ffd48b591d19256884a969fe4da17caryclark}
24455888e44171ffd48b591d19256884a969fe4da17caryclark
24555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
24626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
24755888e44171ffd48b591d19256884a969fe4da17caryclark    contourList->globalState()->debugSetCheckHealth(true);
24855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
24926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    GlitchLog glitches;
25026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpContour* contour = contourList;
25126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpCoincidence* coincidence = contour->globalState()->coincidence();
25255888e44171ffd48b591d19256884a969fe4da17caryclark    coincidence->debugCheckValid(id, &glitches); // don't call validate; spans may be inconsistent
25326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
25426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        contour->debugCheckHealth(id, &glitches);
25555888e44171ffd48b591d19256884a969fe4da17caryclark        contour->debugMissingCoincidence(id, &glitches);
25626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((contour = contour->next()));
25755888e44171ffd48b591d19256884a969fe4da17caryclark    coincidence->debugRemoveCollapsed(id, &glitches);
25826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugAddMissing(id, &glitches);
25926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugExpand(id, &glitches);
26026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugAddExpanded(id, &glitches);
26126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugMark(id, &glitches);
26255888e44171ffd48b591d19256884a969fe4da17caryclark    coincidence->debugReorder(id, &glitches);
26326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    unsigned mask = 0;
26426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < glitches.fGlitches.count(); ++index) {
26526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SpanGlitch& glitch = glitches.fGlitches[index];
26626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        mask |= 1 << glitch.fType;
26726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
26826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < kGlitchType_Count; ++index) {
26926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(mask & (1 << index) ? "x" : "-");
27026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
27126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("  %s\n", id);
27255888e44171ffd48b591d19256884a969fe4da17caryclark    for (int index = 0; index < glitches.fGlitches.count(); ++index) {
27355888e44171ffd48b591d19256884a969fe4da17caryclark        const SpanGlitch& glitch = glitches.fGlitches[index];
27455888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf("%02d: ", index);
27555888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fBase) {
27655888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" base=%d", glitch.fBase->debugID());
27755888e44171ffd48b591d19256884a969fe4da17caryclark        }
27855888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fSuspect) {
27955888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" base=%d", glitch.fSuspect->debugID());
28055888e44171ffd48b591d19256884a969fe4da17caryclark        }
28155888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fSegment) {
28255888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" segment=%d", glitch.fSegment->debugID());
28355888e44171ffd48b591d19256884a969fe4da17caryclark        }
28455888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fCoinSpan) {
28555888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" coinSpan=%d", glitch.fCoinSpan->debugID());
28655888e44171ffd48b591d19256884a969fe4da17caryclark        }
28755888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fEndSpan) {
28855888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID());
28955888e44171ffd48b591d19256884a969fe4da17caryclark        }
29055888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppSpan) {
29155888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppSpan=%d", glitch.fOppSpan->debugID());
29255888e44171ffd48b591d19256884a969fe4da17caryclark        }
29355888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppEndSpan) {
29455888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID());
29555888e44171ffd48b591d19256884a969fe4da17caryclark        }
29655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fStartT)) {
29755888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" startT=%g", glitch.fStartT);
29855888e44171ffd48b591d19256884a969fe4da17caryclark        }
29955888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fEndT)) {
30055888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" endT=%g", glitch.fEndT);
30155888e44171ffd48b591d19256884a969fe4da17caryclark        }
30255888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppSegment) {
30355888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" segment=%d", glitch.fOppSegment->debugID());
30455888e44171ffd48b591d19256884a969fe4da17caryclark        }
30555888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fOppStartT)) {
30655888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppStartT=%g", glitch.fOppStartT);
30755888e44171ffd48b591d19256884a969fe4da17caryclark        }
30855888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fOppEndT)) {
30955888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppEndT=%g", glitch.fOppEndT);
31055888e44171ffd48b591d19256884a969fe4da17caryclark        }
31155888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) {
31255888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY);
31355888e44171ffd48b591d19256884a969fe4da17caryclark        }
31455888e44171ffd48b591d19256884a969fe4da17caryclark        switch (glitch.fType) {
31555888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break;
31655888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break;
31755888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break;
31855888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break;
31955888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break;
32055888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break;
32155888e44171ffd48b591d19256884a969fe4da17caryclark            case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break;
32255888e44171ffd48b591d19256884a969fe4da17caryclark            case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break;
32355888e44171ffd48b591d19256884a969fe4da17caryclark            case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break;
32455888e44171ffd48b591d19256884a969fe4da17caryclark            case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break;
32555888e44171ffd48b591d19256884a969fe4da17caryclark            case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break;
32655888e44171ffd48b591d19256884a969fe4da17caryclark            case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break;
32755888e44171ffd48b591d19256884a969fe4da17caryclark            case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break;
32855888e44171ffd48b591d19256884a969fe4da17caryclark            case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break;
32955888e44171ffd48b591d19256884a969fe4da17caryclark            case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break;
33055888e44171ffd48b591d19256884a969fe4da17caryclark            case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break;
33155888e44171ffd48b591d19256884a969fe4da17caryclark            case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break;
33255888e44171ffd48b591d19256884a969fe4da17caryclark            case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break;
33355888e44171ffd48b591d19256884a969fe4da17caryclark            case kMergeContained_Glitch: SkDebugf(" MergeContained"); break;
33455888e44171ffd48b591d19256884a969fe4da17caryclark            case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break;
33555888e44171ffd48b591d19256884a969fe4da17caryclark            case kMissingDone_Glitch: SkDebugf(" MissingDone"); break;
33655888e44171ffd48b591d19256884a969fe4da17caryclark            case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break;
33755888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break;
33855888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break;
33955888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break;
34055888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break;
34155888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break;
34255888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break;
34355888e44171ffd48b591d19256884a969fe4da17caryclark            case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break;
34455888e44171ffd48b591d19256884a969fe4da17caryclark            case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break;
34555888e44171ffd48b591d19256884a969fe4da17caryclark            case kUnaligned_Glitch: SkDebugf(" Unaligned"); break;
34655888e44171ffd48b591d19256884a969fe4da17caryclark            case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break;
34755888e44171ffd48b591d19256884a969fe4da17caryclark            case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break;
34855888e44171ffd48b591d19256884a969fe4da17caryclark            default: SkASSERT(0);
34955888e44171ffd48b591d19256884a969fe4da17caryclark        }
35055888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf("\n");
35155888e44171ffd48b591d19256884a969fe4da17caryclark    }
35255888e44171ffd48b591d19256884a969fe4da17caryclark    contourList->globalState()->debugSetCheckHealth(false);
35355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS
35455888e44171ffd48b591d19256884a969fe4da17caryclark    SkDebugf("active after %s:\n", id);
35555888e44171ffd48b591d19256884a969fe4da17caryclark    ShowActiveSpans(contourList);
35655888e44171ffd48b591d19256884a969fe4da17caryclark#endif
35755888e44171ffd48b591d19256884a969fe4da17caryclark#endif
35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
35926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
3604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE
362570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
36307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    size_t len = strlen(str);
36407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool num = false;
36507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    for (size_t idx = 0; idx < len; ++idx) {
36607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (num && str[idx] == 'e') {
36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (len + 2 >= bufferLen) {
36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                return;
36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
37007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            memmove(&str[idx + 2], &str[idx + 1], len - idx);
37107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx] = '*';
37207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx + 1] = '^';
37307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++len;
37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
37507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        num = str[idx] >= '0' && str[idx] <= '9';
37607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
37707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
37807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
379570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) {
38007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
383570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) {
38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (wind == SK_MinS32) {
38507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("?");
38607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
38707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%d", wind);
38807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
38907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
39054359294a7c9dc54802d512a5d891a35c1663392caryclark#endif //  defined SK_DEBUG || !FORCE_RELEASE
39154359294a7c9dc54802d512a5d891a35c1663392caryclark
392a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
39307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME
394385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; }
395cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
396385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); }
397a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
398570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) {
39907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    char* num = test + strlen(test);
40007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    while (num[-1] >= '0' && num[-1] <= '9') {
40107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        --num;
40207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
40307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (num[0] == '\0') {
40407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
40507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
40607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    int dec = atoi(num);
40707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (dec == 0) {
40807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
40907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
41007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    ++dec;
41107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec);
412a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com}
413a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif
414570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
4151049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) {
4161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName);
4171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (strcmp("skphealth_com76", functionName) == 0) {
4181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("found it\n");
4191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
4201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
4211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
4221049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = {
4231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kDifference_SkPathOp",
4241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kIntersect_SkPathOp",
4251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kUnion_SkPathOp",
42655888e44171ffd48b591d19256884a969fe4da17caryclark    "kXOR_PathOp",
4271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kReverseDifference_SkPathOp",
4281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
4291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
43003b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) {
43103b03cad01628146bbb8d4f33c073bd0c77ee558caryclark    return gOpStrs[op];
43203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark}
43303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark
4341049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) {
4351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]);
4361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("}\n");
4371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
4381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
439086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex);
4401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
4411049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
4421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* testName) {
4431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkAutoMutexAcquire ac(gTestMutex);
4441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_function_header(testName);
4451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(a, "path", true);
4461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(b, "pathB", true);
4471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_op(shapeOp, "path", "pathB");
4484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
4494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
45027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h"
45126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h"
45226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h"
45326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
45426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
45526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt,
45626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkIntersectionHelper& wn) {
45726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
45826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index;
45926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) {
46026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
46126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
46226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = i->debugLoopCount(looper);
46326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = wt.segment()->verb();
46426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb();
46526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8);
46626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(),
46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint));
46826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(),
46926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint));
47026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = wt.weight();
47126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = wn.weight();
47226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
47326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    i->debugResetLoopCount();
47426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
47526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
47626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) {
47726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
47826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) {
47926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
48026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
48126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = local->fDebugLoopCount[index];
48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2];
48326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1];
48426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4],
48526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                sizeof(SkPoint) * 8);
48626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2];
48726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1];
48826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
48926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    local->debugResetLoopCounts();
49026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
49126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
49226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) {
49326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!verb) {
49426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
49526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
49626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* verbs[] = { "", "line", "quad", "conic", "cubic" };
49726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("%s: {{", verbs[verb]);
49826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int ptCount = SkPathOpsVerbToPoints(verb);
49926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index <= ptCount; ++index) {
50026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint::Dump((&pts)[index]);
50126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (index < ptCount - 1) {
50226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf(", ");
50326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
50426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
50526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}");
50626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (weight != 1) {
50726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(", ");
50826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (weight == floorf(weight)) {
50926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%.0f", weight);
51026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } else {
51126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%1.9gf", weight);
51226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
51326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
51426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}\n");
51526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
51626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
51726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() {
51826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* loops[] = { "iterations", "coinChecks", "perpCalcs" };
51926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("\n");
52026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
52126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]);
52226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4],
52326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2]);
52426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4],
52526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2 + 1]);
52626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
52726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
52826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
52926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() {
53026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
53126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb));
53226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts));
53326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight));
53426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
53526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
53627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
53727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG
53827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const {
53927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE
54027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return FLAGS_runFail;
54127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else
54227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return false;
54327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif
54427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark}
54527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif
54627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
54726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
54826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) {
54926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    fDebugLoopCount[index]++;
55026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
55126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
55226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const {
55326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return fDebugLoopCount[index];
55426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
55526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
55626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() {
55726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
55826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
55926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
56026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
561624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h"
562624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsQuad.h"
563624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
564624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const {
565624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDCubic cubic;
566624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[0] = fPts[0];
567624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2] = fPts[1];
568624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[3] = fPts[2];
569624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3;
570624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3;
571624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3;
572624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3;
573624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return cubic;
574624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
575624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
576ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() {
577ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    fLeft = fTop = fRight = fBottom = SK_ScalarNaN;
578ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark}
579ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark
5804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h"
581570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h"
582570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
58455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT()
58555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* SkOpSegment::debugAddT(double t, AliasMatch allowAlias, bool* allocated) const {
58655888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
58755888e44171ffd48b591d19256884a969fe4da17caryclark    SkPoint pt = this->ptAtT(t);
58855888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* span = &fHead;
58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
59055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* result = span->ptT();
59155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* loop;
59255888e44171ffd48b591d19256884a969fe4da17caryclark        bool duplicatePt;
59355888e44171ffd48b591d19256884a969fe4da17caryclark        if (t == result->fT) {
59455888e44171ffd48b591d19256884a969fe4da17caryclark            goto bumpSpan;
59555888e44171ffd48b591d19256884a969fe4da17caryclark        }
59655888e44171ffd48b591d19256884a969fe4da17caryclark        if (this->match(result, this, t, pt, allowAlias)) {
59755888e44171ffd48b591d19256884a969fe4da17caryclark            // see if any existing alias matches segment, pt, and t
59855888e44171ffd48b591d19256884a969fe4da17caryclark            loop = result->next();
59955888e44171ffd48b591d19256884a969fe4da17caryclark            duplicatePt = false;
60055888e44171ffd48b591d19256884a969fe4da17caryclark            while (loop != result) {
60155888e44171ffd48b591d19256884a969fe4da17caryclark                bool ptMatch = loop->fPt == pt;
60255888e44171ffd48b591d19256884a969fe4da17caryclark                if (loop->segment() == this && loop->fT == t && ptMatch) {
60355888e44171ffd48b591d19256884a969fe4da17caryclark                    goto bumpSpan;
60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
60555888e44171ffd48b591d19256884a969fe4da17caryclark                duplicatePt |= ptMatch;
60655888e44171ffd48b591d19256884a969fe4da17caryclark                loop = loop->next();
60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
60855888e44171ffd48b591d19256884a969fe4da17caryclark            if (kNoAliasMatch == allowAlias) {
60955888e44171ffd48b591d19256884a969fe4da17caryclark    bumpSpan:
61055888e44171ffd48b591d19256884a969fe4da17caryclark//                 span->bumpSpanAdds();
61155888e44171ffd48b591d19256884a969fe4da17caryclark                return result;
61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
61355888e44171ffd48b591d19256884a969fe4da17caryclark//             SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator);
61455888e44171ffd48b591d19256884a969fe4da17caryclark//             alias->init(result->span(), t, pt, duplicatePt);
61555888e44171ffd48b591d19256884a969fe4da17caryclark//             result->insert(alias);
61655888e44171ffd48b591d19256884a969fe4da17caryclark//             result->span()->unaligned();
61755888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
61855888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T
61955888e44171ffd48b591d19256884a969fe4da17caryclark//             SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n",  __FUNCTION__, t,
62055888e44171ffd48b591d19256884a969fe4da17caryclark//                     alias->segment()->debugID(), alias->span()->debugID());
62155888e44171ffd48b591d19256884a969fe4da17caryclark// #endif
62255888e44171ffd48b591d19256884a969fe4da17caryclark//             span->bumpSpanAdds();
62355888e44171ffd48b591d19256884a969fe4da17caryclark            if (allocated) {
62455888e44171ffd48b591d19256884a969fe4da17caryclark                *allocated = true;
62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
62655888e44171ffd48b591d19256884a969fe4da17caryclark            return nullptr;
62755888e44171ffd48b591d19256884a969fe4da17caryclark        }
62855888e44171ffd48b591d19256884a969fe4da17caryclark        if (t < result->fT) {
62955888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpan* prev = result->span()->prev();
63055888e44171ffd48b591d19256884a969fe4da17caryclark            if (!prev) {
63155888e44171ffd48b591d19256884a969fe4da17caryclark                return nullptr;  // FIXME: this is a fail case; nullptr return elsewhere means result was allocated in non-const version
63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
63355888e44171ffd48b591d19256884a969fe4da17caryclark//             SkOpSpan* span = insert(prev, allocator);
63455888e44171ffd48b591d19256884a969fe4da17caryclark//             span->init(this, prev, t, pt);
63555888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
63655888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T
63755888e44171ffd48b591d19256884a969fe4da17caryclark//             SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t,
63855888e44171ffd48b591d19256884a969fe4da17caryclark//                     span->segment()->debugID(), span->debugID());
63955888e44171ffd48b591d19256884a969fe4da17caryclark// #endif
64055888e44171ffd48b591d19256884a969fe4da17caryclark//             span->bumpSpanAdds();
64155888e44171ffd48b591d19256884a969fe4da17caryclark            if (allocated) {
64255888e44171ffd48b591d19256884a969fe4da17caryclark                *allocated = true;
64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
64455888e44171ffd48b591d19256884a969fe4da17caryclark            return nullptr;
64555888e44171ffd48b591d19256884a969fe4da17caryclark        }
64655888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(span != &fTail);
64755888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((span = span->upCast()->next()));
64855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(0);
64955888e44171ffd48b591d19256884a969fe4da17caryclark    return nullptr;
65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const {
65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* base = &fHead;
65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* span;
65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* angle = base->fromAngle();
65955888e44171ffd48b591d19256884a969fe4da17caryclark        if (angle && angle->debugCheckCoincidence()) {
66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (base->final()) {
66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark             break;
66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        span = base->upCast();
66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        angle = span->toAngle();
66755888e44171ffd48b591d19256884a969fe4da17caryclark        if (angle && angle->debugCheckCoincidence()) {
66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
66926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
67026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((base = span->next()));
67126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
67226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
67326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
67455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
67526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence
67626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
67726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugMoveMultiples(id, glitches);
67826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugMoveNearby(id, glitches);
67955888e44171ffd48b591d19256884a969fe4da17caryclark    debugMissingCoincidence(id, glitches);
68055888e44171ffd48b591d19256884a969fe4da17caryclark}
68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
68255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll()
68355888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearAll(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
68455888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpan* span = &fHead;
68555888e44171ffd48b591d19256884a969fe4da17caryclark    do {
68655888e44171ffd48b591d19256884a969fe4da17caryclark        this->debugClearOne(span, id, glitches);
68755888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((span = span->next()->upCastable()));
68855888e44171ffd48b591d19256884a969fe4da17caryclark    this->globalState()->coincidence()->debugRelease(id, glitches, this);
68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
69155888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne()
69255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
69355888e44171ffd48b591d19256884a969fe4da17caryclark    if (span->windValue()) glitches->record(kCollapsedWindValue_Glitch, id, span);
69455888e44171ffd48b591d19256884a969fe4da17caryclark    if (span->oppValue()) glitches->record(kCollapsedOppValue_Glitch, id, span);
69555888e44171ffd48b591d19256884a969fe4da17caryclark    if (!span->done()) glitches->record(kCollapsedDone_Glitch, id, span);
69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
69954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() {
70096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpAngle* result = nullptr;
70154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* span = this->head();
70254359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
70354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->toAngle()) {
704dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!result);
70554359294a7c9dc54802d512a5d891a35c1663392caryclark            result = span->toAngle();
706dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
70754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((span = span->next()->upCastable()));
708dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkASSERT(result);
709dac1d17027dcaa5596885a9f333979418b35001ccaryclark    return result;
710dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
711dac1d17027dcaa5596885a9f333979418b35001ccaryclark
71226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
71355888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited
71455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) {
71555888e44171ffd48b591d19256884a969fe4da17caryclark    // reset visited flag back to false
71655888e44171ffd48b591d19256884a969fe4da17caryclark    do {
71755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
71855888e44171ffd48b591d19256884a969fe4da17caryclark        while ((ptT = ptT->next()) != stopPtT) {
71955888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* opp = ptT->segment();
72055888e44171ffd48b591d19256884a969fe4da17caryclark            opp->resetDebugVisited();
72155888e44171ffd48b591d19256884a969fe4da17caryclark        }
72255888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!span->final() && (span = span->upCast()->next()));
72355888e44171ffd48b591d19256884a969fe4da17caryclark}
72455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
72555888e44171ffd48b591d19256884a969fe4da17caryclark
72655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
72755888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence()
72855888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves
72955888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear
73055888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed
73155888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given
73255888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C:
73355888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near
73455888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C.
73555888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2,
73655888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B.
73755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const {
73826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (this->done()) {
73926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
74026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
74126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* prior = nullptr;
74226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* spanBase = &fHead;
74355888e44171ffd48b591d19256884a969fe4da17caryclark//    bool result = false;
74426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
74526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
74626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(ptT->span() == spanBase);
74726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((ptT = ptT->next()) != spanStopPtT) {
74826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT->deleted()) {
74926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
75026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
75155888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* opp = ptT->span()->segment();
75226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (opp->done()) {
75326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
75426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
75526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
75655888e44171ffd48b591d19256884a969fe4da17caryclark            if (!opp->debugVisited()) {
75726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
75826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
75926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (spanBase == &fHead) {
76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
76255888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() == this) {
76355888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
76455888e44171ffd48b591d19256884a969fe4da17caryclark            }
76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* span = spanBase->upCastable();
76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // FIXME?: this assumes that if the opposite segment is coincident then no more
76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // coincidence needs to be detected. This may not be true.
76855888e44171ffd48b591d19256884a969fe4da17caryclark            if (span && span->segment() != opp && span->containsCoincidence(opp)) {  // debug has additional condition since it may be called before inner duplicate points have been deleted
76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
77155888e44171ffd48b591d19256884a969fe4da17caryclark            if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) {  // debug has additional condition since it may be called before inner duplicate points have been deleted
77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
77355888e44171ffd48b591d19256884a969fe4da17caryclark            }
77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* priorPtT = nullptr, * priorStopPtT;
77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find prior span containing opp segment
77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* priorOpp = nullptr;
77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* priorTest = spanBase->prev();
77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while (!priorOpp && priorTest) {
77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorStopPtT = priorPtT = priorTest->ptT();
78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((priorPtT = priorPtT->next()) != priorStopPtT) {
78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (priorPtT->deleted()) {
78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        continue;
78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
78426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkOpSegment* segment = priorPtT->span()->segment();
78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (segment == opp) {
78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        prior = priorTest;
78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        priorOpp = opp;
78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        break;
78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorTest = priorTest->prev();
79226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!priorOpp) {
79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
79655888e44171ffd48b591d19256884a969fe4da17caryclark            if (priorPtT == ptT) {
79755888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
79855888e44171ffd48b591d19256884a969fe4da17caryclark            }
79926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppStart = prior->ptT();
80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppEnd = spanBase->ptT();
80126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool swapped = priorPtT->fT > ptT->fT;
80226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
80326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
80426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(oppStart, oppEnd);
80526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
80655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpCoincidence* coincidence = this->globalState()->coincidence();
80755888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT();
80855888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootPtT = ptT->span()->ptT();
80955888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootOppStart = oppStart->span()->ptT();
81055888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootOppEnd = oppEnd->span()->ptT();
81155888e44171ffd48b591d19256884a969fe4da17caryclark            if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) {
81226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                goto swapBack;
81326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
81455888e44171ffd48b591d19256884a969fe4da17caryclark            if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) {
81555888e44171ffd48b591d19256884a969fe4da17caryclark            // mark coincidence
81655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
81755888e44171ffd48b591d19256884a969fe4da17caryclark//                 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__,
81855888e44171ffd48b591d19256884a969fe4da17caryclark//                         rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(),
81955888e44171ffd48b591d19256884a969fe4da17caryclark//                         rootOppEnd->debugID());
82055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, oppEnd);
82255888e44171ffd48b591d19256884a969fe4da17caryclark                //   coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd);
82355888e44171ffd48b591d19256884a969fe4da17caryclark                // }
82455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
825d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark//                SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd);
82655888e44171ffd48b591d19256884a969fe4da17caryclark#endif
82755888e44171ffd48b591d19256884a969fe4da17caryclark                // result = true;
82826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
82926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    swapBack:
83026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
83126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
83226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
83326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
83426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next()));
83555888e44171ffd48b591d19256884a969fe4da17caryclark    DebugClearVisited(&fHead);
83655888e44171ffd48b591d19256884a969fe4da17caryclark    return;
83726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
83826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
83955888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples()
84055888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed
84126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
84255888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
84326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* test = &fHead;
84426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
84526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        int addCount = test->spanAddsCount();
84626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(addCount >= 1);
84726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (addCount == 1) {
84826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
84926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
85026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* startPtT = test->ptT();
85126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* testPtT = startPtT;
85226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {  // iterate through all spans associated with start
85326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppSpan = testPtT->span();
85426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->spanAddsCount() == addCount) {
85526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
85626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
85726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->deleted()) {
85826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
85926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
86026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* oppSegment = oppSpan->segment();
86126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSegment == this) {
86226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find range of spans to consider merging
86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppPrev = oppSpan;
86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppFirst = oppSpan;
86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppPrev = oppPrev->prev())) {
86826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppPrev->t(), oppSpan->t())) {
86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->spanAddsCount() == addCount) {
87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
87326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
87426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->deleted()) {
87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
87626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppFirst = oppPrev;
87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppNext = oppSpan;
88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppLast = oppSpan;
88126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) {
88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppNext->t(), oppSpan->t())) {
88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->spanAddsCount() == addCount) {
88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
88726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
88826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->deleted()) {
88926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppLast = oppNext;
89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
89326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppFirst == oppLast) {
89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
89526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
89626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppTest = oppFirst;
89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            do {
89826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppTest == oppSpan) {
89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // check to see if the candidate meets specific criteria:
90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // it contains spans of segments in test's loop but not including 'this'
90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppStartPtT = oppTest->ptT();
90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppPtT = oppStartPtT;
90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((oppPtT = oppPtT->next()) != oppStartPtT) {
90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpSegment* oppPtTSegment = oppPtT->segment();
90726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (oppPtTSegment == this) {
90826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        goto tryNextSpan;
90926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpPtT* matchPtT = startPtT;
91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    do {
91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        if (matchPtT->segment() == oppPtTSegment) {
91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            goto foundMatch;
91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        }
91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } while ((matchPtT = matchPtT->next()) != startPtT);
91626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto tryNextSpan;
91726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            foundMatch:  // merge oppTest and oppSpan
91855888e44171ffd48b591d19256884a969fe4da17caryclark                    oppSegment->debugValidate();
91926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) {
92026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse
92126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkASSERT(oppSpan != &oppSegment->fTail);
92226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        glitches->record(kMoveMultiple_Glitch, id, oppTest, oppSpan);
92326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } else {
92426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppTest);
92526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
92655888e44171ffd48b591d19256884a969fe4da17caryclark                    oppSegment->debugValidate();
92726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto checkNextSpan;
92826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
92955888e44171ffd48b591d19256884a969fe4da17caryclark        tryNextSpan:
93026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                ;
93126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()));
93226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((testPtT = testPtT->next()) != startPtT);
93355888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan:
93426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ;
93526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((test = test->final() ? nullptr : test->upCast()->next()));
93655888e44171ffd48b591d19256884a969fe4da17caryclark   debugValidate();
93755888e44171ffd48b591d19256884a969fe4da17caryclark   return;
93826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
93926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
94055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby()
94155888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later.
94226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
94355888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
94455888e44171ffd48b591d19256884a969fe4da17caryclark    // release undeleted spans pointing to this seg that are linked to the primary span
94555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* spanBase = &fHead;
94626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
94755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = spanBase->ptT();
94855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* headPtT = ptT;
94955888e44171ffd48b591d19256884a969fe4da17caryclark        while ((ptT = ptT->next()) != headPtT) {
95055888e44171ffd48b591d19256884a969fe4da17caryclark              const SkOpSpanBase* test = ptT->span();
95155888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() == this && !ptT->deleted() && test != spanBase
95255888e44171ffd48b591d19256884a969fe4da17caryclark                    && test->ptT() == ptT) {
95355888e44171ffd48b591d19256884a969fe4da17caryclark                if (test->final()) {
95455888e44171ffd48b591d19256884a969fe4da17caryclark                    if (spanBase == &fHead) {
95555888e44171ffd48b591d19256884a969fe4da17caryclark                        glitches->record(kMoveNearbyClearAll_Glitch, id, this);
95655888e44171ffd48b591d19256884a969fe4da17caryclark//                        return;
95755888e44171ffd48b591d19256884a969fe4da17caryclark                    }
95855888e44171ffd48b591d19256884a969fe4da17caryclark                    glitches->record(kMoveNearbyReleaseFinal_Glitch, id, spanBase, ptT);
95955888e44171ffd48b591d19256884a969fe4da17caryclark                } else if (test->prev()) {
96055888e44171ffd48b591d19256884a969fe4da17caryclark                    glitches->record(kMoveNearbyRelease_Glitch, id, test, headPtT);
96155888e44171ffd48b591d19256884a969fe4da17caryclark                }
96255888e44171ffd48b591d19256884a969fe4da17caryclark//                break;
96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
96555888e44171ffd48b591d19256884a969fe4da17caryclark        spanBase = spanBase->upCast()->next();
96655888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!spanBase->final());
96755888e44171ffd48b591d19256884a969fe4da17caryclark
96855888e44171ffd48b591d19256884a969fe4da17caryclark    // This loop looks for adjacent spans which are near by
96955888e44171ffd48b591d19256884a969fe4da17caryclark    spanBase = &fHead;
97055888e44171ffd48b591d19256884a969fe4da17caryclark    do {  // iterate through all spans associated with start
97155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* test = spanBase->upCast()->next();
97255888e44171ffd48b591d19256884a969fe4da17caryclark        if (this->spansNearby(spanBase, test)) {
97355888e44171ffd48b591d19256884a969fe4da17caryclark            if (test->final()) {
97455888e44171ffd48b591d19256884a969fe4da17caryclark                if (spanBase->prev()) {
97555888e44171ffd48b591d19256884a969fe4da17caryclark                    glitches->record(kMoveNearbyMergeFinal_Glitch, id, test);
97655888e44171ffd48b591d19256884a969fe4da17caryclark                } else {
97755888e44171ffd48b591d19256884a969fe4da17caryclark                    glitches->record(kMoveNearbyClearAll2_Glitch, id, this);
97855888e44171ffd48b591d19256884a969fe4da17caryclark                    // return
97955888e44171ffd48b591d19256884a969fe4da17caryclark                }
98055888e44171ffd48b591d19256884a969fe4da17caryclark            } else {
98155888e44171ffd48b591d19256884a969fe4da17caryclark                glitches->record(kMoveNearbyMerge_Glitch, id, spanBase);
98255888e44171ffd48b591d19256884a969fe4da17caryclark            }
98355888e44171ffd48b591d19256884a969fe4da17caryclark        }
98455888e44171ffd48b591d19256884a969fe4da17caryclark        spanBase = test;
98555888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!spanBase->final());
98655888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
9904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() {
9911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    this->init(this->fPts, this->fWeight, this->contour(), this->verb());
9924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
9934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
99454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS
9954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const {
9964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    debugValidate();
9974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (done()) {
9984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return;
9994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
10004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int lastId = -1;
10014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double lastT = -1;
100254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* span = &fHead;
100354359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
100454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->done()) {
10054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
10064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
10071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (lastId == this->debugID() && lastT == span->t()) {
10084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
10094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
10101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        lastId = this->debugID();
101154359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = span->t();
10121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%s id=%d", __FUNCTION__, this->debugID());
101355888e44171ffd48b591d19256884a969fe4da17caryclark        // since endpoints may have be adjusted, show actual computed curves
101455888e44171ffd48b591d19256884a969fe4da17caryclark        SkDCurve curvePart;
101555888e44171ffd48b591d19256884a969fe4da17caryclark        this->subDivide(span, span->next(), &curvePart);
101655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkDPoint* pts = curvePart.fCubic.fPts;
101755888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY);
10184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
101955888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY);
10204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
10211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (SkPath::kConic_Verb == fVerb) {
102255888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" %1.9gf", curvePart.fConic.fWeight);
10231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
102455888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t());
102554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->windSum() == SK_MinS32) {
1026624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" windSum=?");
10274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
1028624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" windSum=%d", span->windSum());
1029624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1030624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() && span->oppSum() == SK_MinS32) {
1031624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppSum=?");
1032624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        } else if (span->oppValue() || span->oppSum() != SK_MinS32) {
1033624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppSum=%d", span->oppSum());
1034624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1035624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDebugf(" windValue=%d", span->windValue());
1036624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() || span->oppSum() != SK_MinS32) {
1037624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppValue=%d", span->oppValue());
10384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
103954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
104054359294a7c9dc54802d512a5d891a35c1663392caryclark   } while ((span = span->next()->upCastable()));
10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
104454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE
104554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) {
104654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
10471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
10484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
10494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
10504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
10514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
105254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
105354359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t());
105454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
10554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
10564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
105754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
10584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
105954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windSum=");
106054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
106154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
106254359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
106354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
106454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
106554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d\n", span->windValue());
10664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
10674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
106854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding,
10694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                      int oppWinding) {
107054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
10711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
10724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
10734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
10744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
10754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
107654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
107754359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding);
107854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
107954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
108054359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
108154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
108254359294a7c9dc54802d512a5d891a35c1663392caryclark    }
108354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" newOppSum=");
108454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (oppWinding == SK_MinS32) {
108554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
108654359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
108754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", oppWinding);
108854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
108954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" oppSum=");
109054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->oppSum() == SK_MinS32) {
10914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
10924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
109354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->oppSum());
10944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
10954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" windSum=");
109654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
10974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
109954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
11004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
110154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue());
11024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
110354359294a7c9dc54802d512a5d891a35c1663392caryclark
11044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
11054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
110626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted
110726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted.
110826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark   This should be rarely called -- the test below is thorough and time consuming.
110955888e44171ffd48b591d19256884a969fe4da17caryclark   This checks the distance between start points; the distance between
111026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/
111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const {
111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpAngle* test = this;
111426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
111526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* testSegment = test->segment();
111626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testStartT = test->start()->t();
111726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testStartPt = testSegment->dPtAtT(testStartT);
111826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testEndT = test->end()->t();
111926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testEndPt = testSegment->dPtAtT(testEndT);
112026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testLenSq = testStartPt.distanceSquared(testEndPt);
112126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID());
112226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testMidT = (testStartT + testEndT) / 2;
112326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* next = test;
112426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((next = next->fNext) != this) {
112526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkOpSegment* nextSegment = next->segment();
112626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testMidDistSq = testSegment->distSq(testMidT, next);
112726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testEndDistSq = testSegment->distSq(testEndT, next);
112826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextStartT = next->start()->t();
112926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT);
113026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double distSq = testStartPt.distanceSquared(nextStartPt);
113126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndT = next->end()->t();
113226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidT = (nextStartT + nextEndT) / 2;
113326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidDistSq = nextSegment->distSq(nextMidT, test);
113426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndDistSq = nextSegment->distSq(nextEndT, test);
113526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq,
113626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    testSegment->debugID(), nextSegment->debugID());
113726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq);
113826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq);
113926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq);
114026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq);
114126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT);
114226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextLenSq = nextStartPt.distanceSquared(nextEndPt);
114326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq);
114426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("\n");
114526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
114626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        test = test->fNext;
114755888e44171ffd48b591d19256884a969fe4da17caryclark    } while (test->fNext != this);
114826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
114926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
115026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
115154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE
115254359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const {
115354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkString result;
115454359294a7c9dc54802d512a5d891a35c1663392caryclark    switch (this->segment()->verb()) {
115554359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kLine_Verb:
115654359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart),
115754359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
115854359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
115954359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kQuad_Verb:
116054359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart),
116154359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
116254359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
11631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        case SkPath::kConic_Verb:
11641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            result.printf(CONIC_DEBUG_STR " id=%d",
11651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    CONIC_DEBUG_DATA(fCurvePart, fCurvePart.fConic.fWeight),
11661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    this->segment()->debugID());
11671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            break;
116854359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kCubic_Verb:
116954359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart),
117054359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
117154359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
117254359294a7c9dc54802d512a5d891a35c1663392caryclark        default:
117354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(0);
11741b24933e52f50773de29332387a12721811f3012mtklein    }
117554359294a7c9dc54802d512a5d891a35c1663392caryclark    return result;
117654359294a7c9dc54802d512a5d891a35c1663392caryclark}
117754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
117854359294a7c9dc54802d512a5d891a35c1663392caryclark
1179624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
118054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const {
118154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
118254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
118354359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
118454359294a7c9dc54802d512a5d891a35c1663392caryclark        next->dumpOne(true);
118554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
118654359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
118754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
118854359294a7c9dc54802d512a5d891a35c1663392caryclark    next = first;
118954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
119054359294a7c9dc54802d512a5d891a35c1663392caryclark        next->debugValidate();
119154359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
119254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
1193ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1194ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
1195ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
119654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const {
119755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
119855888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
119955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
120055888e44171ffd48b591d19256884a969fe4da17caryclark    }
120155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
120254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
120354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
120454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
120554359294a7c9dc54802d512a5d891a35c1663392caryclark    int wind = 0;
120654359294a7c9dc54802d512a5d891a35c1663392caryclark    int opp = 0;
120754359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastXor = -1;
120854359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastOppXor = -1;
120954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
121054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next->unorderable()) {
121154359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
121254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
121354359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpan* minSpan = next->start()->starter(next->end());
121454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (minSpan->windValue() == SK_MinS32) {
121554359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
121654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
121754359294a7c9dc54802d512a5d891a35c1663392caryclark        bool op = next->segment()->operand();
121854359294a7c9dc54802d512a5d891a35c1663392caryclark        bool isXor = next->segment()->isXor();
121954359294a7c9dc54802d512a5d891a35c1663392caryclark        bool oppXor = next->segment()->oppXor();
122054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM));
122154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM
122254359294a7c9dc54802d512a5d891a35c1663392caryclark                || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM));
122354359294a7c9dc54802d512a5d891a35c1663392caryclark        bool useXor = op ? oppXor : isXor;
122454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastXor == -1 || lastXor == (int) useXor);
122554359294a7c9dc54802d512a5d891a35c1663392caryclark        lastXor = (int) useXor;
1226624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue());
122754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
122854359294a7c9dc54802d512a5d891a35c1663392caryclark            wind &= 1;
122954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
123054359294a7c9dc54802d512a5d891a35c1663392caryclark        useXor = op ? isXor : oppXor;
123154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor);
123254359294a7c9dc54802d512a5d891a35c1663392caryclark        lastOppXor = (int) useXor;
1233624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue());
123454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
123554359294a7c9dc54802d512a5d891a35c1663392caryclark            opp &= 1;
123654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
123754359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
123854359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
1239182b499cd75c971f85cdf52c1827b3c220cc9011caryclark    SkASSERT(wind == 0 || !FLAGS_runFail);
124054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(opp == 0 || !FLAGS_runFail);
124154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
124254359294a7c9dc54802d512a5d891a35c1663392caryclark}
124354359294a7c9dc54802d512a5d891a35c1663392caryclark
124454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const {
124554359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE
124654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
124754359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = first;
124854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkTDArray<const SkOpAngle*>(angles);
124954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
1250f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen//        SkASSERT_RELEASE(next->fSegment->debugContains(next));
125154359294a7c9dc54802d512a5d891a35c1663392caryclark        angles.push(next);
125254359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->next();
125354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next == first) {
125454359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
125554359294a7c9dc54802d512a5d891a35c1663392caryclark        }
1256f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen        SkASSERT_RELEASE(!angles.contains(next));
125754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!next) {
125854359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
125954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
126054359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (true);
126154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
126254359294a7c9dc54802d512a5d891a35c1663392caryclark}
126354359294a7c9dc54802d512a5d891a35c1663392caryclark
126455888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG
126555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over,
126655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpGlobalState* debugState) const {
126755888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail());
126855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail());
126955888e44171ffd48b591d19256884a969fe4da17caryclark}
127055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
127255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
127355888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */
127455888e44171ffd48b591d19256884a969fe4da17caryclarkbool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const {
127555888e44171ffd48b591d19256884a969fe4da17caryclark    bool expanded = false;
127655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* segment = coinPtTStart()->segment();
127755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* oppSegment = oppPtTStart()->segment();
127855888e44171ffd48b591d19256884a969fe4da17caryclark    do {
127955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* start = coinPtTStart()->span()->upCast();
128055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* prev = start->prev();
128155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oppPtT;
128255888e44171ffd48b591d19256884a969fe4da17caryclark        if (!prev || !(oppPtT = prev->contains(oppSegment))) {
128355888e44171ffd48b591d19256884a969fe4da17caryclark            break;
128455888e44171ffd48b591d19256884a969fe4da17caryclark        }
128555888e44171ffd48b591d19256884a969fe4da17caryclark        double midT = (prev->t() + start->t()) / 2;
128655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!segment->isClose(midT, oppSegment)) {
128755888e44171ffd48b591d19256884a969fe4da17caryclark            break;
128855888e44171ffd48b591d19256884a969fe4da17caryclark        }
128955888e44171ffd48b591d19256884a969fe4da17caryclark        if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT);
129055888e44171ffd48b591d19256884a969fe4da17caryclark        expanded = true;
129155888e44171ffd48b591d19256884a969fe4da17caryclark    } while (false);  // actual continues while expansion is possible
129255888e44171ffd48b591d19256884a969fe4da17caryclark    do {
129355888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coinPtTEnd()->span();
129455888e44171ffd48b591d19256884a969fe4da17caryclark        SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next();
129555888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oppPtT;
129655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!next || !(oppPtT = next->contains(oppSegment))) {
129755888e44171ffd48b591d19256884a969fe4da17caryclark            break;
129855888e44171ffd48b591d19256884a969fe4da17caryclark        }
129955888e44171ffd48b591d19256884a969fe4da17caryclark        double midT = (end->t() + next->t()) / 2;
130055888e44171ffd48b591d19256884a969fe4da17caryclark        if (!segment->isClose(midT, oppSegment)) {
130155888e44171ffd48b591d19256884a969fe4da17caryclark            break;
130255888e44171ffd48b591d19256884a969fe4da17caryclark        }
130355888e44171ffd48b591d19256884a969fe4da17caryclark        if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT);
130455888e44171ffd48b591d19256884a969fe4da17caryclark        expanded = true;
130555888e44171ffd48b591d19256884a969fe4da17caryclark    } while (false);  // actual continues while expansion is possible
130655888e44171ffd48b591d19256884a969fe4da17caryclark    return expanded;
130755888e44171ffd48b591d19256884a969fe4da17caryclark}
130855888e44171ffd48b591d19256884a969fe4da17caryclark
130955888e44171ffd48b591d19256884a969fe4da17caryclark#define FAIL_IF(cond)  do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false)
131055888e44171ffd48b591d19256884a969fe4da17caryclark
131155888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */
131255888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans
131355888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span
131426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* log) const {
131526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = this->fHead;
131626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
1317ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark        return;
1318ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    }
131926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
132055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* startPtT = coin->coinPtTStart();
132155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oStartPtT = coin->oppPtTStart();
132226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(startPtT->contains(oStartPtT));
132355888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd()));
132426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* start = startPtT->span();
132526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oStart = oStartPtT->span();
132655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coin->coinPtTEnd()->span();
132755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span();
132855888e44171ffd48b591d19256884a969fe4da17caryclark        FAIL_IF(oEnd->deleted());
132926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* test = start->upCast()->next();
133055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next();
133155888e44171ffd48b591d19256884a969fe4da17caryclark        if (!oTest) {
133255888e44171ffd48b591d19256884a969fe4da17caryclark            return;
133355888e44171ffd48b591d19256884a969fe4da17caryclark        }
133426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while (test != end || oTest != oEnd) {
133555888e44171ffd48b591d19256884a969fe4da17caryclark            if (!test->ptT()->contains(oTest->segment())
133655888e44171ffd48b591d19256884a969fe4da17caryclark                    || !oTest->ptT()->contains(start->segment())) {
133726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // use t ranges to guess which one is missing
133855888e44171ffd48b591d19256884a969fe4da17caryclark                double startRange = coin->coinPtTEnd()->fT - startPtT->fT;
133955888e44171ffd48b591d19256884a969fe4da17caryclark                FAIL_IF(!startRange);
134026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double startPart = (test->t() - startPtT->fT) / startRange;
134155888e44171ffd48b591d19256884a969fe4da17caryclark                double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT;
134255888e44171ffd48b591d19256884a969fe4da17caryclark                FAIL_IF(!oStartRange);
134326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
134455888e44171ffd48b591d19256884a969fe4da17caryclark                FAIL_IF(startPart == oStartPart);
134555888e44171ffd48b591d19256884a969fe4da17caryclark                bool startOver = false;
134655888e44171ffd48b591d19256884a969fe4da17caryclark                if (startPart < oStartPart)
134755888e44171ffd48b591d19256884a969fe4da17caryclark                        log->record(kAddExpandedCoin_Glitch, id,  // strange debug formatting lines up with original
134855888e44171ffd48b591d19256884a969fe4da17caryclark                                oStartPtT->fT + oStartRange * startPart, test);
134955888e44171ffd48b591d19256884a969fe4da17caryclark                        else log->record(kAddExpandedCoin_Glitch, id,
135055888e44171ffd48b591d19256884a969fe4da17caryclark                                startPtT->fT + startRange * oStartPart, oTest);
135155888e44171ffd48b591d19256884a969fe4da17caryclark                if (false) {
135255888e44171ffd48b591d19256884a969fe4da17caryclark                    SkASSERT(0);
135355888e44171ffd48b591d19256884a969fe4da17caryclark                    return;
135426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
135555888e44171ffd48b591d19256884a969fe4da17caryclark                if (startOver) {
135655888e44171ffd48b591d19256884a969fe4da17caryclark                    test = start;
135755888e44171ffd48b591d19256884a969fe4da17caryclark                    oTest = oStart;
135826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
135926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
136055888e44171ffd48b591d19256884a969fe4da17caryclark            if (test != end) {
136126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                test = test->upCast()->next();
136226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
136355888e44171ffd48b591d19256884a969fe4da17caryclark            if (oTest != oEnd) {
136455888e44171ffd48b591d19256884a969fe4da17caryclark                oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next();
136555888e44171ffd48b591d19256884a969fe4da17caryclark                if (!oTest) {
136655888e44171ffd48b591d19256884a969fe4da17caryclark                    return;
136755888e44171ffd48b591d19256884a969fe4da17caryclark                }
136826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
136926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
137055888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
137155888e44171ffd48b591d19256884a969fe4da17caryclark    return;
137255888e44171ffd48b591d19256884a969fe4da17caryclark}
137355888e44171ffd48b591d19256884a969fe4da17caryclark
137455888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addIfMissing() */
137555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s,
137655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog* log) const {
137755888e44171ffd48b591d19256884a969fe4da17caryclark//     SkASSERT(fTop);
137855888e44171ffd48b591d19256884a969fe4da17caryclark    if (fTop && alreadyAdded(fTop, outer, over1s, over1e)) {  // in debug, fTop may be null
137955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
138026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
138155888e44171ffd48b591d19256884a969fe4da17caryclark    if (fHead && alreadyAdded(fHead, outer, over1s, over1e)) {
138255888e44171ffd48b591d19256884a969fe4da17caryclark        return;
138355888e44171ffd48b591d19256884a969fe4da17caryclark    }
138455888e44171ffd48b591d19256884a969fe4da17caryclark    log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coinPtTEnd(), over1s, over1e);
138555888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
138655888e44171ffd48b591d19256884a969fe4da17caryclark    return;
138726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
138826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
138955888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */
139055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
139155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd,
139255888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
139355888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, const char* id, SkPathOpsDebug::GlitchLog* log) const {
139426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double coinTs, coinTe, oppTs, oppTe;
139555888e44171ffd48b591d19256884a969fe4da17caryclark    TRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe);
139655888e44171ffd48b591d19256884a969fe4da17caryclark    TRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe);
139755888e44171ffd48b591d19256884a969fe4da17caryclark    bool swap = coinTs > coinTe;
139855888e44171ffd48b591d19256884a969fe4da17caryclark    if (swap) {
139955888e44171ffd48b591d19256884a969fe4da17caryclark        SkTSwap(coinTs, coinTe);
140026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
140126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) {
140226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(oppTs, oppTe);
140326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
140455888e44171ffd48b591d19256884a969fe4da17caryclark    if (swap) {
140526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(oppTs, oppTe);
140626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
140755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* coinSeg = coinPtTStart->segment();
140855888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* oppSeg = oppPtTStart->segment();
140955888e44171ffd48b591d19256884a969fe4da17caryclark    if (coinSeg == oppSeg) {
141055888e44171ffd48b591d19256884a969fe4da17caryclark        return;
141126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
141255888e44171ffd48b591d19256884a969fe4da17caryclark    return this->debugAddOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, id, log);
141355888e44171ffd48b591d19256884a969fe4da17caryclark}
141455888e44171ffd48b591d19256884a969fe4da17caryclark
141555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */
141655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
141755888e44171ffd48b591d19256884a969fe4da17caryclark        double coinTs, double coinTe, double oppTs, double oppTe, const char* id, SkPathOpsDebug::GlitchLog* log) const {
141855888e44171ffd48b591d19256884a969fe4da17caryclark    SkTDArray<SkCoincidentSpans*> overlaps;
141955888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(!fTop);   // this is (correctly) reversed in addifMissing()
142055888e44171ffd48b591d19256884a969fe4da17caryclark    if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) {
142155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
142255888e44171ffd48b591d19256884a969fe4da17caryclark    }
142355888e44171ffd48b591d19256884a969fe4da17caryclark    if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs,
142455888e44171ffd48b591d19256884a969fe4da17caryclark            coinTe, oppTs, oppTe, &overlaps)) {
142555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
142655888e44171ffd48b591d19256884a969fe4da17caryclark    }
142755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr;
142855888e44171ffd48b591d19256884a969fe4da17caryclark    for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing
142955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkCoincidentSpans* test = overlaps[index];
143055888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) {
143155888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart());
143255888e44171ffd48b591d19256884a969fe4da17caryclark        }
143355888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) {
143455888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd());
143555888e44171ffd48b591d19256884a969fe4da17caryclark        }
143655888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->flipped()
143755888e44171ffd48b591d19256884a969fe4da17caryclark                ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT
143855888e44171ffd48b591d19256884a969fe4da17caryclark                : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) {
143955888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart());
144055888e44171ffd48b591d19256884a969fe4da17caryclark        }
144155888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->flipped()
144255888e44171ffd48b591d19256884a969fe4da17caryclark                ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT
144355888e44171ffd48b591d19256884a969fe4da17caryclark                : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) {
144455888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd());
144555888e44171ffd48b591d19256884a969fe4da17caryclark        }
144655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!fHead) {
144755888e44171ffd48b591d19256884a969fe4da17caryclark            SkAssertResult(true);
144855888e44171ffd48b591d19256884a969fe4da17caryclark        }
144955888e44171ffd48b591d19256884a969fe4da17caryclark    }
145055888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg);
145155888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg);
145255888e44171ffd48b591d19256884a969fe4da17caryclark    if (overlap && cs && ce && overlap->contains(cs, ce)) {
145355888e44171ffd48b591d19256884a969fe4da17caryclark        return;
145455888e44171ffd48b591d19256884a969fe4da17caryclark    }
145555888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(cs != ce || !cs);
145655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg);
145755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg);
145855888e44171ffd48b591d19256884a969fe4da17caryclark    if (overlap && os && oe && overlap->contains(os, oe)) {
145955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
146055888e44171ffd48b591d19256884a969fe4da17caryclark    }
146155888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !cs || !cs->deleted());
146255888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !os || !os->deleted());
146355888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !ce || !ce->deleted());
146455888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !oe || !oe->deleted());
146555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr;
146655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr;
146755888e44171ffd48b591d19256884a969fe4da17caryclark    if (csExisting && csExisting == ceExisting) {
146855888e44171ffd48b591d19256884a969fe4da17caryclark        return;
146955888e44171ffd48b591d19256884a969fe4da17caryclark    }
147055888e44171ffd48b591d19256884a969fe4da17caryclark    if (csExisting && (csExisting == ce || csExisting->contains(ceExisting ? ceExisting : ce))) {
147155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
147255888e44171ffd48b591d19256884a969fe4da17caryclark    }
147355888e44171ffd48b591d19256884a969fe4da17caryclark    if (ceExisting && (ceExisting == cs || ceExisting->contains(csExisting ? csExisting : cs))) {
147455888e44171ffd48b591d19256884a969fe4da17caryclark        return;
147555888e44171ffd48b591d19256884a969fe4da17caryclark    }
147655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr;
147755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr;
147855888e44171ffd48b591d19256884a969fe4da17caryclark    if (osExisting && osExisting == oeExisting) {
147955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
148055888e44171ffd48b591d19256884a969fe4da17caryclark    }
148155888e44171ffd48b591d19256884a969fe4da17caryclark    if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeExisting : oe))) {
148255888e44171ffd48b591d19256884a969fe4da17caryclark        return;
148355888e44171ffd48b591d19256884a969fe4da17caryclark    }
148455888e44171ffd48b591d19256884a969fe4da17caryclark    if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osExisting : os))) {
148555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
148655888e44171ffd48b591d19256884a969fe4da17caryclark    }
148755888e44171ffd48b591d19256884a969fe4da17caryclark    bool csDeleted = false, osDeleted = false, ceDeleted = false,  oeDeleted = false;
148855888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
148955888e44171ffd48b591d19256884a969fe4da17caryclark    if (!cs || !os) {
149055888e44171ffd48b591d19256884a969fe4da17caryclark        if (!cs)
149155888e44171ffd48b591d19256884a969fe4da17caryclark            cs = coinSeg->debugAddT(coinTs, SkOpSegment::kNoAliasMatch, nullptr);
149255888e44171ffd48b591d19256884a969fe4da17caryclark        if (!os)
149355888e44171ffd48b591d19256884a969fe4da17caryclark            os = oppSeg->debugAddT(oppTs, SkOpSegment::kNoAliasMatch, nullptr);
149455888e44171ffd48b591d19256884a969fe4da17caryclark        if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDeleted, &osDeleted);
149555888e44171ffd48b591d19256884a969fe4da17caryclark//         cs = csWritable;
149655888e44171ffd48b591d19256884a969fe4da17caryclark//         os = osWritable;
149755888e44171ffd48b591d19256884a969fe4da17caryclark        if ((ce && ce->deleted()) || (oe && oe->deleted())) {
149855888e44171ffd48b591d19256884a969fe4da17caryclark            return;
149955888e44171ffd48b591d19256884a969fe4da17caryclark        }
150055888e44171ffd48b591d19256884a969fe4da17caryclark    }
150155888e44171ffd48b591d19256884a969fe4da17caryclark    if (!ce || !oe) {
150255888e44171ffd48b591d19256884a969fe4da17caryclark        if (!ce)
150355888e44171ffd48b591d19256884a969fe4da17caryclark            ce = coinSeg->debugAddT(coinTe, SkOpSegment::kNoAliasMatch, nullptr);
150455888e44171ffd48b591d19256884a969fe4da17caryclark        if (!oe)
150555888e44171ffd48b591d19256884a969fe4da17caryclark            oe = oppSeg->debugAddT(oppTe, SkOpSegment::kNoAliasMatch, nullptr);
150655888e44171ffd48b591d19256884a969fe4da17caryclark        if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDeleted, &oeDeleted);
150755888e44171ffd48b591d19256884a969fe4da17caryclark//         ce = ceWritable;
150855888e44171ffd48b591d19256884a969fe4da17caryclark//         oe = oeWritable;
150955888e44171ffd48b591d19256884a969fe4da17caryclark    }
151055888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
151155888e44171ffd48b591d19256884a969fe4da17caryclark    if (csDeleted || osDeleted || ceDeleted || oeDeleted) {
151255888e44171ffd48b591d19256884a969fe4da17caryclark        return;
151355888e44171ffd48b591d19256884a969fe4da17caryclark    }
151455888e44171ffd48b591d19256884a969fe4da17caryclark    if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) {
151555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
151655888e44171ffd48b591d19256884a969fe4da17caryclark    }
151755888e44171ffd48b591d19256884a969fe4da17caryclark//     bool result = true;
151855888e44171ffd48b591d19256884a969fe4da17caryclark    if (overlap) {
151955888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTStart()->segment() == coinSeg) {
152055888e44171ffd48b591d19256884a969fe4da17caryclark                log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
152155888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
152255888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppTs > oppTe) {
152355888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(coinTs, coinTe);
152455888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(oppTs, oppTe);
152555888e44171ffd48b591d19256884a969fe4da17caryclark            }
152655888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe);
152755888e44171ffd48b591d19256884a969fe4da17caryclark        }
152855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
152955888e44171ffd48b591d19256884a969fe4da17caryclark//         if (result) {
153055888e44171ffd48b591d19256884a969fe4da17caryclark//             overlap->debugShow();
153155888e44171ffd48b591d19256884a969fe4da17caryclark//         }
153255888e44171ffd48b591d19256884a969fe4da17caryclark#endif
153355888e44171ffd48b591d19256884a969fe4da17caryclark    } else {
153455888e44171ffd48b591d19256884a969fe4da17caryclark        log->record(kAddMissingCoin_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
153555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
153655888e44171ffd48b591d19256884a969fe4da17caryclark//         fHead->debugShow();
153755888e44171ffd48b591d19256884a969fe4da17caryclark#endif
153855888e44171ffd48b591d19256884a969fe4da17caryclark    }
153955888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
154055888e44171ffd48b591d19256884a969fe4da17caryclark    return;
154126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
154226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
154355888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing()
154455888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */
154555888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */
154655888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again
154726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const {
154826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* outer = fHead;
154926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!outer) {
155026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
155126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
155255888e44171ffd48b591d19256884a969fe4da17caryclark    // bool added = false;
155355888e44171ffd48b591d19256884a969fe4da17caryclark    // fTop = outer;
155455888e44171ffd48b591d19256884a969fe4da17caryclark    // fHead = nullptr;
155526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
155626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing can modify the list that this is walking
155726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // save head so that walker can iterate over old data unperturbed
155826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing adds to head freely then add saved head in the end
155955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* outerCoin = outer->coinPtTStart()->segment();
156055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* outerOpp = outer->oppPtTStart()->segment();
156155888e44171ffd48b591d19256884a969fe4da17caryclark        if (outerCoin->done() || outerOpp->done()) {
156255888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
156355888e44171ffd48b591d19256884a969fe4da17caryclark        }
156426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkCoincidentSpans* inner = outer;
156555888e44171ffd48b591d19256884a969fe4da17caryclark        while ((inner = inner->next())) {
156655888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
156726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double overS, overE;
156855888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* innerCoin = inner->coinPtTStart()->segment();
156955888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* innerOpp = inner->oppPtTStart()->segment();
157055888e44171ffd48b591d19256884a969fe4da17caryclark            if (innerCoin->done() || innerOpp->done()) {
157155888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
157255888e44171ffd48b591d19256884a969fe4da17caryclark            }
157355888e44171ffd48b591d19256884a969fe4da17caryclark            if (outerCoin == innerCoin) {
157455888e44171ffd48b591d19256884a969fe4da17caryclark                if (outerOpp != innerOpp
157555888e44171ffd48b591d19256884a969fe4da17caryclark                        && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(),
157655888e44171ffd48b591d19256884a969fe4da17caryclark                        inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) {
157755888e44171ffd48b591d19256884a969fe4da17caryclark                    this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(),
157855888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE,
157955888e44171ffd48b591d19256884a969fe4da17caryclark                            outer->oppPtTStart(), outer->oppPtTEnd(),
158055888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->oppPtTStart(), inner->oppPtTEnd(), id, log);
158126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
158255888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerCoin == innerOpp) {
158355888e44171ffd48b591d19256884a969fe4da17caryclark                if (outerOpp != innerCoin
158455888e44171ffd48b591d19256884a969fe4da17caryclark                        && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(),
158555888e44171ffd48b591d19256884a969fe4da17caryclark                        inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) {
158655888e44171ffd48b591d19256884a969fe4da17caryclark                    this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(),
158755888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE,
158855888e44171ffd48b591d19256884a969fe4da17caryclark                            outer->oppPtTStart(), outer->oppPtTEnd(),
158955888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->coinPtTStart(), inner->coinPtTEnd(), id, log);
159026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
159155888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerOpp == innerCoin) {
159255888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(outerCoin != innerOpp);
159355888e44171ffd48b591d19256884a969fe4da17caryclark                if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(),
159455888e44171ffd48b591d19256884a969fe4da17caryclark                        inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) {
159555888e44171ffd48b591d19256884a969fe4da17caryclark                    this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(),
159655888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE,
159755888e44171ffd48b591d19256884a969fe4da17caryclark                            outer->coinPtTStart(), outer->coinPtTEnd(),
159855888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->oppPtTStart(), inner->oppPtTEnd(), id, log);
159926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
160055888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerOpp == innerOpp) {
160155888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(outerCoin != innerCoin);
160255888e44171ffd48b591d19256884a969fe4da17caryclark                if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(),
160355888e44171ffd48b591d19256884a969fe4da17caryclark                        inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) {
160455888e44171ffd48b591d19256884a969fe4da17caryclark                    this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(),
160555888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE,
160655888e44171ffd48b591d19256884a969fe4da17caryclark                            outer->coinPtTStart(), outer->coinPtTEnd(),
160755888e44171ffd48b591d19256884a969fe4da17caryclark                            inner->coinPtTStart(), inner->coinPtTEnd(), id, log);
160826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
160926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
161055888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
161155888e44171ffd48b591d19256884a969fe4da17caryclark        }
161255888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((outer = outer->next()));
161355888e44171ffd48b591d19256884a969fe4da17caryclark    // this->restoreHead();
161455888e44171ffd48b591d19256884a969fe4da17caryclark    return;
161555888e44171ffd48b591d19256884a969fe4da17caryclark}
161655888e44171ffd48b591d19256884a969fe4da17caryclark
161755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release()
161855888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const {
161955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* coin = fHead;
162055888e44171ffd48b591d19256884a969fe4da17caryclark    if (!coin) {
162155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
162255888e44171ffd48b591d19256884a969fe4da17caryclark    }
162355888e44171ffd48b591d19256884a969fe4da17caryclark    do {
162455888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->coinPtTStart()->segment() == deleted
162555888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->coinPtTEnd()->segment() == deleted
162655888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->oppPtTStart()->segment() == deleted
162755888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->oppPtTEnd()->segment() == deleted) {
162855888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kReleasedSpan_Glitch, id, coin);
162955888e44171ffd48b591d19256884a969fe4da17caryclark        }
163055888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
163155888e44171ffd48b591d19256884a969fe4da17caryclark}
163255888e44171ffd48b591d19256884a969fe4da17caryclark
163355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with reorder()
163455888e44171ffd48b591d19256884a969fe4da17caryclark// iterate through all coincident pairs, looking for ranges greater than 1
163555888e44171ffd48b591d19256884a969fe4da17caryclark// if found, see if the opposite pair can match it -- which may require
163655888e44171ffd48b591d19256884a969fe4da17caryclark// reordering the ptT pairs
163755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* log) const {
163855888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* coin = fHead;
163955888e44171ffd48b591d19256884a969fe4da17caryclark    if (!coin) {
164055888e44171ffd48b591d19256884a969fe4da17caryclark        return;
164155888e44171ffd48b591d19256884a969fe4da17caryclark    }
164255888e44171ffd48b591d19256884a969fe4da17caryclark    do {
164355888e44171ffd48b591d19256884a969fe4da17caryclark        // most commonly, concidence are one span long; check for that first
164455888e44171ffd48b591d19256884a969fe4da17caryclark        int intervals = coin->spanCount();
164555888e44171ffd48b591d19256884a969fe4da17caryclark        if (intervals = 1) {
164655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
164755888e44171ffd48b591d19256884a969fe4da17caryclark            // SkASSERT(!coin->debugExpand(nullptr, nullptr));
164855888e44171ffd48b591d19256884a969fe4da17caryclark#endif
164955888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
165055888e44171ffd48b591d19256884a969fe4da17caryclark        }
165155888e44171ffd48b591d19256884a969fe4da17caryclark        coin->debugExpand(id, log);
165255888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->spanCount() <= 0) {
165355888e44171ffd48b591d19256884a969fe4da17caryclark            return;
165426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
165555888e44171ffd48b591d19256884a969fe4da17caryclark        // check to see if every span in coin has a mate in opp
165655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* start = coin->coinPtTStart()->span()->upCast();
165755888e44171ffd48b591d19256884a969fe4da17caryclark        bool flipped = coin->flipped();
165855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oppStartBase = coin->oppPtTStart()->span();
165955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* oppStart = flipped ? oppStartBase->prev() : oppStartBase->upCast();
166055888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf("", start, oppStart);
166155888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
166255888e44171ffd48b591d19256884a969fe4da17caryclark    return;
166326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
166426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
166555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand()
166655888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence
166726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const {
166826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
166926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
167026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return false;
167126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
167226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    bool expanded = false;
167326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
167455888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->debugExpand(id, log)) {
167555888e44171ffd48b591d19256884a969fe4da17caryclark            // check to see if multiple spans expanded so they are now identical
167655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkCoincidentSpans* test = fHead;
167755888e44171ffd48b591d19256884a969fe4da17caryclark            do {
167855888e44171ffd48b591d19256884a969fe4da17caryclark                if (coin == test) {
167955888e44171ffd48b591d19256884a969fe4da17caryclark                    continue;
168055888e44171ffd48b591d19256884a969fe4da17caryclark                }
168155888e44171ffd48b591d19256884a969fe4da17caryclark                if (coin->coinPtTStart() == test->coinPtTStart()
168255888e44171ffd48b591d19256884a969fe4da17caryclark                        && coin->oppPtTStart() == test->oppPtTStart()) {
168355888e44171ffd48b591d19256884a969fe4da17caryclark                    if (log) log->record(kExpandCoin_Glitch, id, fHead, test->coinPtTStart());
168455888e44171ffd48b591d19256884a969fe4da17caryclark                    break;
168555888e44171ffd48b591d19256884a969fe4da17caryclark                }
168655888e44171ffd48b591d19256884a969fe4da17caryclark            } while ((test = test->next()));
168755888e44171ffd48b591d19256884a969fe4da17caryclark            expanded = true;
168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
168955888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
169026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return expanded;
169126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
169226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
169355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with removeCollapsed()
169455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRemoveCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log) const {
169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
169626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
169726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
169826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
169955888e44171ffd48b591d19256884a969fe4da17caryclark    // SkCoincidentSpans** priorPtr = &fHead;
170026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
170155888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->coinPtTStart() == coin->coinPtTEnd()) {
170255888e44171ffd48b591d19256884a969fe4da17caryclark            return;
170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
170455888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->oppPtTStart() == coin->oppPtTEnd()) {
170555888e44171ffd48b591d19256884a969fe4da17caryclark            return;
170626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
170755888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->coinPtTStart()->collapsed(coin->coinPtTEnd())) {
170855888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kCollapsedCoin_Glitch, id, coin);
170955888e44171ffd48b591d19256884a969fe4da17caryclark//             continue;
171026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
171155888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->oppPtTStart()->collapsed(coin->oppPtTEnd())) {
171255888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kCollapsedCoin_Glitch, id, coin, coin);
171355888e44171ffd48b591d19256884a969fe4da17caryclark//             continue;
171426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
171555888e44171ffd48b591d19256884a969fe4da17caryclark        // priorPtr = &coin->nextPtr();
171655888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
171755888e44171ffd48b591d19256884a969fe4da17caryclark    return;
171826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
171926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
172055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark()
172155888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */
172226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const {
172326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
172426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
172526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
172626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
172726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
172855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast();
172955888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(start->deleted());
173055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coin->coinPtTEndWritable()->span();
173155888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(end->deleted());
173255888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span();
173355888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(oStart->deleted());
173455888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span();
173555888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(oEnd->deleted());
173655888e44171ffd48b591d19256884a969fe4da17caryclark        bool flipped = coin->flipped();
173726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (flipped) {
173826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkTSwap(oStart, oEnd);
173926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
174055888e44171ffd48b591d19256884a969fe4da17caryclark        /* coin and opp spans may not match up. Mark the ends, and then let the interior
174155888e44171ffd48b591d19256884a969fe4da17caryclark           get marked as many times as the spans allow */
174255888e44171ffd48b591d19256884a969fe4da17caryclark        start->debugInsertCoincidence(id, log, oStart->upCast());
174355888e44171ffd48b591d19256884a969fe4da17caryclark        end->debugInsertCoinEnd(id, log, oEnd);
174455888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* segment = start->segment();
174555888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* oSegment = oStart->segment();
174626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* next = start;
174726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oNext = oStart;
174855888e44171ffd48b591d19256884a969fe4da17caryclark        while ((next = next->upCast()->next()) != end) {
174955888e44171ffd48b591d19256884a969fe4da17caryclark            if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flipped), false) {
175055888e44171ffd48b591d19256884a969fe4da17caryclark                return;
175126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
175255888e44171ffd48b591d19256884a969fe4da17caryclark        }
175355888e44171ffd48b591d19256884a969fe4da17caryclark        while ((oNext = oNext->upCast()->next()) != oEnd) {
175455888e44171ffd48b591d19256884a969fe4da17caryclark            if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flipped), false) {
175555888e44171ffd48b591d19256884a969fe4da17caryclark                return;
175626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
175755888e44171ffd48b591d19256884a969fe4da17caryclark        }
175855888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
175955888e44171ffd48b591d19256884a969fe4da17caryclark    return;
176055888e44171ffd48b591d19256884a969fe4da17caryclark}
176155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
176255888e44171ffd48b591d19256884a969fe4da17caryclark
176355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
176455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed()
176555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const {
176655888e44171ffd48b591d19256884a969fe4da17caryclark    while (coin) {
176755888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->collapsed(test)) {
176855888e44171ffd48b591d19256884a969fe4da17caryclark            if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) {
176955888e44171ffd48b591d19256884a969fe4da17caryclark                log->record(kCollapsedCoin_Glitch, id, coin);
177026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
177155888e44171ffd48b591d19256884a969fe4da17caryclark            if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) {
177255888e44171ffd48b591d19256884a969fe4da17caryclark                log->record(kCollapsedCoin_Glitch, id, coin);
177355888e44171ffd48b591d19256884a969fe4da17caryclark            }
177455888e44171ffd48b591d19256884a969fe4da17caryclark        }
177555888e44171ffd48b591d19256884a969fe4da17caryclark        coin = coin->next();
177655888e44171ffd48b591d19256884a969fe4da17caryclark    }
177755888e44171ffd48b591d19256884a969fe4da17caryclark}
177855888e44171ffd48b591d19256884a969fe4da17caryclark
177955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed()
178055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const {
178155888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugMarkCollapsed(id, log, fHead, test);
178255888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugMarkCollapsed(id, log, fTop, test);
178326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
178426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
178526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
178655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const {
178755888e44171ffd48b591d19256884a969fe4da17caryclark    SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__,
178855888e44171ffd48b591d19256884a969fe4da17caryclark            coinPtTStart()->segment()->debugID(),
178955888e44171ffd48b591d19256884a969fe4da17caryclark            coinPtTStart()->fT, coinPtTEnd()->fT);
179055888e44171ffd48b591d19256884a969fe4da17caryclark    SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__,
179155888e44171ffd48b591d19256884a969fe4da17caryclark            oppPtTStart()->segment()->debugID(),
179255888e44171ffd48b591d19256884a969fe4da17caryclark            oppPtTStart()->fT, oppPtTEnd()->fT);
179355888e44171ffd48b591d19256884a969fe4da17caryclark}
179455888e44171ffd48b591d19256884a969fe4da17caryclark
1795624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const {
179655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
179755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* span = fHead;
1798624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    while (span) {
179955888e44171ffd48b591d19256884a969fe4da17caryclark        span->debugShow();
180055888e44171ffd48b591d19256884a969fe4da17caryclark        span = span->next();
1801624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
180255888e44171ffd48b591d19256884a969fe4da17caryclark#endif
1803624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
1804624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
180526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
180655888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end,
180755888e44171ffd48b591d19256884a969fe4da17caryclark        double oStart, double oEnd, const SkOpSegment* oSegment,
180855888e44171ffd48b591d19256884a969fe4da17caryclark        const char* id, SkPathOpsDebug::GlitchLog* log) {
180955888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(next != end);
181055888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(!next->contains(end) || log);
181155888e44171ffd48b591d19256884a969fe4da17caryclark    if (next->t() > end->t()) {
181255888e44171ffd48b591d19256884a969fe4da17caryclark        SkTSwap(next, end);
181355888e44171ffd48b591d19256884a969fe4da17caryclark    }
181455888e44171ffd48b591d19256884a969fe4da17caryclark    do {
181555888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = next->ptT();
181655888e44171ffd48b591d19256884a969fe4da17caryclark        int index = 0;
181755888e44171ffd48b591d19256884a969fe4da17caryclark        bool somethingBetween;
181855888e44171ffd48b591d19256884a969fe4da17caryclark        do {
181955888e44171ffd48b591d19256884a969fe4da17caryclark            ++index;
182055888e44171ffd48b591d19256884a969fe4da17caryclark            ptT = ptT->next();
182155888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* checkPtT = next->ptT();
182255888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT == checkPtT) {
182355888e44171ffd48b591d19256884a969fe4da17caryclark                break;
182455888e44171ffd48b591d19256884a969fe4da17caryclark            }
182555888e44171ffd48b591d19256884a969fe4da17caryclark            bool looped = false;
182655888e44171ffd48b591d19256884a969fe4da17caryclark            for (int check = 0; check < index; ++check) {
182755888e44171ffd48b591d19256884a969fe4da17caryclark                if ((looped = checkPtT == ptT)) {
182855888e44171ffd48b591d19256884a969fe4da17caryclark                    break;
182955888e44171ffd48b591d19256884a969fe4da17caryclark                }
183055888e44171ffd48b591d19256884a969fe4da17caryclark                checkPtT = checkPtT->next();
183155888e44171ffd48b591d19256884a969fe4da17caryclark            }
183255888e44171ffd48b591d19256884a969fe4da17caryclark            if (looped) {
183355888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(0);
183455888e44171ffd48b591d19256884a969fe4da17caryclark                break;
183555888e44171ffd48b591d19256884a969fe4da17caryclark            }
183655888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->deleted()) {
183755888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
183855888e44171ffd48b591d19256884a969fe4da17caryclark            }
183955888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() != oSegment) {
184055888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
184155888e44171ffd48b591d19256884a969fe4da17caryclark            }
184255888e44171ffd48b591d19256884a969fe4da17caryclark            somethingBetween |= between(oStart, ptT->fT, oEnd);
184355888e44171ffd48b591d19256884a969fe4da17caryclark        } while (true);
184455888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(somethingBetween);
184555888e44171ffd48b591d19256884a969fe4da17caryclark    } while (next != end && (next = next->upCast()->next()));
184655888e44171ffd48b591d19256884a969fe4da17caryclark}
184755888e44171ffd48b591d19256884a969fe4da17caryclark
184855888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list,
184955888e44171ffd48b591d19256884a969fe4da17caryclark        const char* id, SkPathOpsDebug::GlitchLog* log) {
185055888e44171ffd48b591d19256884a969fe4da17caryclark    if (!list) {
185155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
185255888e44171ffd48b591d19256884a969fe4da17caryclark    }
185355888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* coinSeg = test->coinPtTStart()->segment();
185455888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(coinSeg == test->coinPtTEnd()->segment());
185555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* oppSeg = test->oppPtTStart()->segment();
185655888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(oppSeg == test->oppPtTEnd()->segment());
185755888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(coinSeg != test->oppPtTStart()->segment());
185855888e44171ffd48b591d19256884a969fe4da17caryclark    SkDEBUGCODE(double tcs = test->coinPtTStart()->fT);
185955888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tcs, 1));
186055888e44171ffd48b591d19256884a969fe4da17caryclark    SkDEBUGCODE(double tce = test->coinPtTEnd()->fT);
186155888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tce, 1));
186255888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(tcs < tce);
186355888e44171ffd48b591d19256884a969fe4da17caryclark    double tos = test->oppPtTStart()->fT;
186455888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tos, 1));
186555888e44171ffd48b591d19256884a969fe4da17caryclark    double toe = test->oppPtTEnd()->fT;
186655888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, toe, 1));
186755888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(tos != toe);
186855888e44171ffd48b591d19256884a969fe4da17caryclark    if (tos > toe) {
186955888e44171ffd48b591d19256884a969fe4da17caryclark        SkTSwap(tos, toe);
187055888e44171ffd48b591d19256884a969fe4da17caryclark    }
187155888e44171ffd48b591d19256884a969fe4da17caryclark    do {
187255888e44171ffd48b591d19256884a969fe4da17caryclark        double lcs, lce, los, loe;
187355888e44171ffd48b591d19256884a969fe4da17caryclark        if (coinSeg == list->coinPtTStart()->segment()) {
187455888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppSeg != list->oppPtTStart()->segment()) {
187555888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
187655888e44171ffd48b591d19256884a969fe4da17caryclark            }
187755888e44171ffd48b591d19256884a969fe4da17caryclark            lcs = list->coinPtTStart()->fT;
187855888e44171ffd48b591d19256884a969fe4da17caryclark            lce = list->coinPtTEnd()->fT;
187955888e44171ffd48b591d19256884a969fe4da17caryclark            los = list->oppPtTStart()->fT;
188055888e44171ffd48b591d19256884a969fe4da17caryclark            loe = list->oppPtTEnd()->fT;
188155888e44171ffd48b591d19256884a969fe4da17caryclark            if (los > loe) {
188255888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(los, loe);
188355888e44171ffd48b591d19256884a969fe4da17caryclark            }
188455888e44171ffd48b591d19256884a969fe4da17caryclark        } else if (coinSeg == list->oppPtTStart()->segment()) {
188555888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppSeg != list->coinPtTStart()->segment()) {
188655888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
188755888e44171ffd48b591d19256884a969fe4da17caryclark            }
188855888e44171ffd48b591d19256884a969fe4da17caryclark            lcs = list->oppPtTStart()->fT;
188955888e44171ffd48b591d19256884a969fe4da17caryclark            lce = list->oppPtTEnd()->fT;
189055888e44171ffd48b591d19256884a969fe4da17caryclark            if (lcs > lce) {
189155888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(lcs, lce);
189255888e44171ffd48b591d19256884a969fe4da17caryclark            }
189355888e44171ffd48b591d19256884a969fe4da17caryclark            los = list->coinPtTStart()->fT;
189455888e44171ffd48b591d19256884a969fe4da17caryclark            loe = list->coinPtTEnd()->fT;
189555888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
189655888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
189755888e44171ffd48b591d19256884a969fe4da17caryclark        }
189855888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(tce < lcs || lce < tcs);
189955888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(toe < los || loe < tos);
190055888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((list = list->next()));
190155888e44171ffd48b591d19256884a969fe4da17caryclark}
190255888e44171ffd48b591d19256884a969fe4da17caryclark
190355888e44171ffd48b591d19256884a969fe4da17caryclark
190455888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt,
190555888e44171ffd48b591d19256884a969fe4da17caryclark        const char* id, SkPathOpsDebug::GlitchLog* log) {
190655888e44171ffd48b591d19256884a969fe4da17caryclark    // check for overlapping coincident spans
190755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* test = head;
190855888e44171ffd48b591d19256884a969fe4da17caryclark    while (test) {
190955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkCoincidentSpans* next = test->next();
191055888e44171ffd48b591d19256884a969fe4da17caryclark        DebugCheckOverlap(test, next, id, log);
191155888e44171ffd48b591d19256884a969fe4da17caryclark        DebugCheckOverlap(test, opt, id, log);
191255888e44171ffd48b591d19256884a969fe4da17caryclark        test = next;
191355888e44171ffd48b591d19256884a969fe4da17caryclark    }
191455888e44171ffd48b591d19256884a969fe4da17caryclark}
191555888e44171ffd48b591d19256884a969fe4da17caryclark
191655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
191755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLog* log) const {
191855888e44171ffd48b591d19256884a969fe4da17caryclark    DebugCheckOverlapTop(fHead, fTop, id, log);
191955888e44171ffd48b591d19256884a969fe4da17caryclark    DebugCheckOverlapTop(fTop, nullptr, id, log);
192055888e44171ffd48b591d19256884a969fe4da17caryclark}
192155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
192255888e44171ffd48b591d19256884a969fe4da17caryclark
192355888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt,
192455888e44171ffd48b591d19256884a969fe4da17caryclark        const char* id, SkPathOpsDebug::GlitchLog* log) {
192555888e44171ffd48b591d19256884a969fe4da17caryclark    // look for pts inside coincident spans that are not inside the opposite spans
192655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* coin = head;
192755888e44171ffd48b591d19256884a969fe4da17caryclark    while (coin) {
192855888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(),
192955888e44171ffd48b591d19256884a969fe4da17caryclark                coin->oppPtTStart()->segment()));
193055888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart());
193155888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd());
193255888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart());
193355888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd());
193455888e44171ffd48b591d19256884a969fe4da17caryclark        DebugValidate(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(),
193555888e44171ffd48b591d19256884a969fe4da17caryclark                coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(),
193655888e44171ffd48b591d19256884a969fe4da17caryclark                id, log);
193755888e44171ffd48b591d19256884a969fe4da17caryclark        DebugValidate(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(),
193855888e44171ffd48b591d19256884a969fe4da17caryclark                coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(),
193955888e44171ffd48b591d19256884a969fe4da17caryclark                id, log);
194055888e44171ffd48b591d19256884a969fe4da17caryclark        coin = coin->next();
194155888e44171ffd48b591d19256884a969fe4da17caryclark    }
194255888e44171ffd48b591d19256884a969fe4da17caryclark    DebugCheckOverlapTop(head, opt, id, log);
194355888e44171ffd48b591d19256884a969fe4da17caryclark}
194455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
194555888e44171ffd48b591d19256884a969fe4da17caryclark
194655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugValidate() const {
194755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
194855888e44171ffd48b591d19256884a969fe4da17caryclark //   if (fGlobalState->debugCheckHealth()) {
194955888e44171ffd48b591d19256884a969fe4da17caryclark//        return;
195055888e44171ffd48b591d19256884a969fe4da17caryclark//    }
195155888e44171ffd48b591d19256884a969fe4da17caryclark    DebugValidate(fHead, fTop, nullptr, nullptr);
195255888e44171ffd48b591d19256884a969fe4da17caryclark    DebugValidate(fTop, nullptr, nullptr, nullptr);
195355888e44171ffd48b591d19256884a969fe4da17caryclark#endif
195455888e44171ffd48b591d19256884a969fe4da17caryclark}
195555888e44171ffd48b591d19256884a969fe4da17caryclark
195655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
195755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const {
195855888e44171ffd48b591d19256884a969fe4da17caryclark    DebugValidate(fHead, fTop, id, log);
195955888e44171ffd48b591d19256884a969fe4da17caryclark    DebugValidate(fTop, nullptr, id, log);
196055888e44171ffd48b591d19256884a969fe4da17caryclark}
196155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
196255888e44171ffd48b591d19256884a969fe4da17caryclark
196355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
196426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* log) const {
196526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = &fHead;
196626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
196726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        segment->debugCheckHealth(id, log);
196826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((segment = segment->next()));
196926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
197026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
197155888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence()
197255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const {
197355888e44171ffd48b591d19256884a969fe4da17caryclark//    SkASSERT(fCount > 0);
197426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = &fHead;
197555888e44171ffd48b591d19256884a969fe4da17caryclark//    bool result = false;
197626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
197755888e44171ffd48b591d19256884a969fe4da17caryclark        if (fState->angleCoincidence()) {
197855888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ANGLE
197955888e44171ffd48b591d19256884a969fe4da17caryclark//          segment->debugCheckAngleCoin();
198055888e44171ffd48b591d19256884a969fe4da17caryclark// #endif
198155888e44171ffd48b591d19256884a969fe4da17caryclark        } else if (segment->debugMissingCoincidence(id, log), false) {
198255888e44171ffd48b591d19256884a969fe4da17caryclark//          result = true;
198355888e44171ffd48b591d19256884a969fe4da17caryclark// see FIXME in missingCoincidence()
198455888e44171ffd48b591d19256884a969fe4da17caryclark//
198555888e44171ffd48b591d19256884a969fe4da17caryclark//
198655888e44171ffd48b591d19256884a969fe4da17caryclark//
198755888e44171ffd48b591d19256884a969fe4da17caryclark    //      continue;
198855888e44171ffd48b591d19256884a969fe4da17caryclark        }
198955888e44171ffd48b591d19256884a969fe4da17caryclark        segment = segment->next();
199055888e44171ffd48b591d19256884a969fe4da17caryclark    } while (segment);
199155888e44171ffd48b591d19256884a969fe4da17caryclark    return;
199226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
199326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
199426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
19954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const {
199655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
199755888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
199855888e44171ffd48b591d19256884a969fe4da17caryclark        return;
199955888e44171ffd48b591d19256884a969fe4da17caryclark    }
200055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
20014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE
200254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* span = &fHead;
200354359294a7c9dc54802d512a5d891a35c1663392caryclark    double lastT = -1;
200496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpSpanBase* prev = nullptr;
200554359294a7c9dc54802d512a5d891a35c1663392caryclark    int count = 0;
20064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int done = 0;
200754359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
200854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!span->final()) {
200954359294a7c9dc54802d512a5d891a35c1663392caryclark            ++count;
201054359294a7c9dc54802d512a5d891a35c1663392caryclark            done += span->upCast()->done() ? 1 : 0;
201154359294a7c9dc54802d512a5d891a35c1663392caryclark        }
201254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(span->segment() == this);
201354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev->upCast()->next() == span);
201454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev == span->prev());
201554359294a7c9dc54802d512a5d891a35c1663392caryclark        prev = span;
201654359294a7c9dc54802d512a5d891a35c1663392caryclark        double t = span->ptT()->fT;
201754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastT < t);
201854359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = t;
201954359294a7c9dc54802d512a5d891a35c1663392caryclark        span->debugValidate();
202054359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (!span->final() && (span = span->upCast()->next()));
202154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(count == fCount);
202254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(done == fDoneCount);
202308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    SkASSERT(count >= fDoneCount);
202454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(span->final());
202554359294a7c9dc54802d512a5d891a35c1663392caryclark    span->debugValidate();
202654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
202754359294a7c9dc54802d512a5d891a35c1663392caryclark}
202854359294a7c9dc54802d512a5d891a35c1663392caryclark
202955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
203055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOppAndMerge()
203155888e44171ffd48b591d19256884a969fe4da17caryclark// If the added points envelop adjacent spans, merge them in.
203255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const {
203355888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->ptT()->debugAddOpp(opp->ptT())) {
203455888e44171ffd48b591d19256884a969fe4da17caryclark        this->debugCheckForCollapsedCoincidence(id, log);
203526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
203655888e44171ffd48b591d19256884a969fe4da17caryclark    // compute bounds of points in span
203755888e44171ffd48b591d19256884a969fe4da17caryclark    SkPathOpsBounds bounds;
203855888e44171ffd48b591d19256884a969fe4da17caryclark    bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin);
203955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* head = this->ptT();
204055888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* nextPt = head;
204155888e44171ffd48b591d19256884a969fe4da17caryclark    do {
204255888e44171ffd48b591d19256884a969fe4da17caryclark        bounds.add(nextPt->fPt);
204355888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((nextPt = nextPt->next()) != head);
204455888e44171ffd48b591d19256884a969fe4da17caryclark    if (!bounds.width() && !bounds.height()) {
204555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
204626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
204755888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugMergeContained(id, log, bounds, spanDeleted);
204855888e44171ffd48b591d19256884a969fe4da17caryclark    opp->debugMergeContained(id, log, bounds, oppDeleted);
204926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
205026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
205155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence()
205255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const {
205355888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpCoincidence* coins = this->globalState()->coincidence();
205455888e44171ffd48b591d19256884a969fe4da17caryclark    if (coins->isEmpty()) {
205555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
205655888e44171ffd48b591d19256884a969fe4da17caryclark    }
205755888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span
205855888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop
205955888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span
206055888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* head = this->ptT();
206155888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* test = head;
206226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
206355888e44171ffd48b591d19256884a969fe4da17caryclark        if (!test->coincident()) {
206455888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
206526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
206655888e44171ffd48b591d19256884a969fe4da17caryclark        coins->debugMarkCollapsed(id, log, test);
206755888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((test = test->next()) != head);
206826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
206955888e44171ffd48b591d19256884a969fe4da17caryclark#endif
207026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
207154359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const {
207254359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
207354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* next = this;
207454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* nextCoin;
207554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
207654359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoinEnd;
207754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin);
207854359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
207954359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* checkCoin = this->fCoinEnd;
208054359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* innerCoin = checkCoin;
208154359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
208254359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoinEnd;
208354359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
208454359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident end loop ***\n");
208554359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
208654359294a7c9dc54802d512a5d891a35c1663392caryclark                }
208754359294a7c9dc54802d512a5d891a35c1663392caryclark            }
208854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
208954359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
209054359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
209154359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
209254359294a7c9dc54802d512a5d891a35c1663392caryclark}
209354359294a7c9dc54802d512a5d891a35c1663392caryclark
209455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
209555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd()
209655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugInsertCoinEnd(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const {
209755888e44171ffd48b591d19256884a969fe4da17caryclark    if (containsCoinEnd(coin)) {
209855888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(coin->containsCoinEnd(this));
209955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
210055888e44171ffd48b591d19256884a969fe4da17caryclark    }
210155888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
210255888e44171ffd48b591d19256884a969fe4da17caryclark//     SkASSERT(this != coin);
210355888e44171ffd48b591d19256884a969fe4da17caryclark    log->record(kMarkCoinEnd_Glitch, id, this, coin);
210455888e44171ffd48b591d19256884a969fe4da17caryclark//     coin->fCoinEnd = this->fCoinEnd;
210555888e44171ffd48b591d19256884a969fe4da17caryclark//     this->fCoinEnd = coinNext;
210655888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
210755888e44171ffd48b591d19256884a969fe4da17caryclark}
210855888e44171ffd48b591d19256884a969fe4da17caryclark
210955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mergeContained()
211055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog* log, const SkPathOpsBounds& bounds, bool* deleted) const {
211155888e44171ffd48b591d19256884a969fe4da17caryclark    // while adjacent spans' points are contained by the bounds, merge them
211255888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* prev = this;
211355888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* seg = this->segment();
211455888e44171ffd48b591d19256884a969fe4da17caryclark    while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisjoint(prev, this)) {
211555888e44171ffd48b591d19256884a969fe4da17caryclark        if (prev->prev()) {
211655888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, this, prev);
211755888e44171ffd48b591d19256884a969fe4da17caryclark        } else if (this->final()) {
211855888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, this, prev);
211955888e44171ffd48b591d19256884a969fe4da17caryclark            // return;
212055888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
212155888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, prev, this);
212226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
212326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
212455888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* current = this;
212555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* next = this;
212655888e44171ffd48b591d19256884a969fe4da17caryclark    while (next->upCastable() && (next = next->upCast()->next())
212755888e44171ffd48b591d19256884a969fe4da17caryclark            && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) {
212855888e44171ffd48b591d19256884a969fe4da17caryclark        if (!current->prev() && next->final()) {
212955888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, next, current);
213055888e44171ffd48b591d19256884a969fe4da17caryclark            current = next;
213155888e44171ffd48b591d19256884a969fe4da17caryclark        }
213255888e44171ffd48b591d19256884a969fe4da17caryclark        if (current->prev()) {
213355888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, next, current);
213455888e44171ffd48b591d19256884a969fe4da17caryclark            current = next;
213555888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
213655888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMergeContained_Glitch, id, next, current);
213755888e44171ffd48b591d19256884a969fe4da17caryclark            current = next;
213855888e44171ffd48b591d19256884a969fe4da17caryclark        }
213955888e44171ffd48b591d19256884a969fe4da17caryclark    }
214055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
214155888e44171ffd48b591d19256884a969fe4da17caryclark    // this->globalState()->coincidence()->debugValidate();
214255888e44171ffd48b591d19256884a969fe4da17caryclark#endif
214326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
214455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
214526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
214626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const {
214726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* end = *endPtr;
214826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() == end->segment());
214926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* result;
215026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (t() < end->t()) {
215126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = this;
215226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } else {
215326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = end;
215426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        *endPtr = this;
215526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
215626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return result->upCast();
215726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
215826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
215954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const {
216055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
216155888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
216255888e44171ffd48b591d19256884a969fe4da17caryclark        return;
216355888e44171ffd48b591d19256884a969fe4da17caryclark    }
216455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
216554359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
216654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* ptT = &fPtT;
216754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(ptT->span() == this);
216854359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
216954359294a7c9dc54802d512a5d891a35c1663392caryclark//        SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt));
217054359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT->debugValidate();
217154359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT = ptT->next();
217254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (ptT != &fPtT);
217354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->debugCoinEndLoopCheck());
217454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final()) {
217554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(this->upCast()->debugCoinLoopCheck());
217654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
217754359294a7c9dc54802d512a5d891a35c1663392caryclark    if (fFromAngle) {
217854359294a7c9dc54802d512a5d891a35c1663392caryclark        fFromAngle->debugValidate();
217954359294a7c9dc54802d512a5d891a35c1663392caryclark    }
218054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final() && this->upCast()->toAngle()) {
218154359294a7c9dc54802d512a5d891a35c1663392caryclark        this->upCast()->toAngle()->debugValidate();
218254359294a7c9dc54802d512a5d891a35c1663392caryclark    }
21834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
218454359294a7c9dc54802d512a5d891a35c1663392caryclark}
218554359294a7c9dc54802d512a5d891a35c1663392caryclark
218654359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const {
218754359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
218854359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* next = this;
218954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* nextCoin;
219054359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
219154359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoincident;
219254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin);
219354359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
219454359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* checkCoin = this->fCoincident;
219554359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* innerCoin = checkCoin;
219654359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
219754359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoincident;
219854359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
219954359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident loop ***\n");
220054359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
220154359294a7c9dc54802d512a5d891a35c1663392caryclark                }
220254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
220354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
220454359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
220554359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
220654359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
220754359294a7c9dc54802d512a5d891a35c1663392caryclark}
220854359294a7c9dc54802d512a5d891a35c1663392caryclark
220955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE
221055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header
221155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const {
221255888e44171ffd48b591d19256884a969fe4da17caryclark    if (containsCoincidence(coin)) {
221355888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(coin->containsCoincidence(this));
221455888e44171ffd48b591d19256884a969fe4da17caryclark        return;
221555888e44171ffd48b591d19256884a969fe4da17caryclark    }
221655888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
221755888e44171ffd48b591d19256884a969fe4da17caryclark//     SkASSERT(this != coin);
221855888e44171ffd48b591d19256884a969fe4da17caryclark    log->record(kMarkCoinStart_Glitch, id, this, coin);
221955888e44171ffd48b591d19256884a969fe4da17caryclark//     coin->fCoincident = this->fCoincident;
222055888e44171ffd48b591d19256884a969fe4da17caryclark//     this->fCoincident = coinNext;
222155888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
222255888e44171ffd48b591d19256884a969fe4da17caryclark}
222355888e44171ffd48b591d19256884a969fe4da17caryclark
222455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence()
222555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped) const {
222655888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->containsCoincidence(segment)) {
222755888e44171ffd48b591d19256884a969fe4da17caryclark        return;
222855888e44171ffd48b591d19256884a969fe4da17caryclark    }
222955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* next = &fPtT;
223055888e44171ffd48b591d19256884a969fe4da17caryclark    while ((next = next->next()) != &fPtT) {
223155888e44171ffd48b591d19256884a969fe4da17caryclark        if (next->segment() == segment) {
223255888e44171ffd48b591d19256884a969fe4da17caryclark            log->record(kMarkCoinInsert_Glitch, id, flipped ? next->span()->prev() : next->span());
223355888e44171ffd48b591d19256884a969fe4da17caryclark            return;
223455888e44171ffd48b591d19256884a969fe4da17caryclark        }
223555888e44171ffd48b591d19256884a969fe4da17caryclark    }
223655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
223755888e44171ffd48b591d19256884a969fe4da17caryclark    log->record(kMarkCoinMissing_Glitch, id, segment, this);
223855888e44171ffd48b591d19256884a969fe4da17caryclark#endif
223955888e44171ffd48b591d19256884a969fe4da17caryclark}
224055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
224155888e44171ffd48b591d19256884a969fe4da17caryclark
2242624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code
2243624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const {
2244624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    if (!fIsCoincident[0]) {
2245624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkASSERT(!fIsCoincident[1]);
2246624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        return 0;
2247624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
2248624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    int count = 0;
2249624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDEBUGCODE(int count2 = 0;)
2250624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    for (int index = 0; index < fUsed; ++index) {
2251624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[0] & (1 << index)) {
2252624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count;
2253624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
2254624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG
2255624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[1] & (1 << index)) {
2256624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count2;
2257624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
2258624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
2259624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
2260624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkASSERT(count == count2);
2261624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return count;
2262624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
2263624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
226454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h"
226554359294a7c9dc54802d512a5d891a35c1663392caryclark
226655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp()
226755888e44171ffd48b591d19256884a969fe4da17caryclarkbool SkOpPtT::debugAddOpp(const SkOpPtT* opp) const {
226855888e44171ffd48b591d19256884a969fe4da17caryclark    // find the fOpp ptr to opp
226955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* oppPrev = opp->fNext;
227055888e44171ffd48b591d19256884a969fe4da17caryclark    if (oppPrev == this) {
227155888e44171ffd48b591d19256884a969fe4da17caryclark        return false;
227255888e44171ffd48b591d19256884a969fe4da17caryclark    }
227355888e44171ffd48b591d19256884a969fe4da17caryclark    while (oppPrev->fNext != opp) {
227455888e44171ffd48b591d19256884a969fe4da17caryclark        oppPrev = oppPrev->fNext;
227555888e44171ffd48b591d19256884a969fe4da17caryclark        if (oppPrev == this) {
227655888e44171ffd48b591d19256884a969fe4da17caryclark            return false;
227755888e44171ffd48b591d19256884a969fe4da17caryclark        }
227855888e44171ffd48b591d19256884a969fe4da17caryclark    }
227955888e44171ffd48b591d19256884a969fe4da17caryclark//    const SkOpPtT* oldNext = this->fNext;
228055888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(this != opp);
228155888e44171ffd48b591d19256884a969fe4da17caryclark//    this->fNext = opp;
228255888e44171ffd48b591d19256884a969fe4da17caryclark//    SkASSERT(oppPrev != oldNext);
228355888e44171ffd48b591d19256884a969fe4da17caryclark//    oppPrev->fNext = oldNext;
228455888e44171ffd48b591d19256884a969fe4da17caryclark    return true;
228555888e44171ffd48b591d19256884a969fe4da17caryclark}
228655888e44171ffd48b591d19256884a969fe4da17caryclark
228726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const {
228826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this != check);
228926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
229026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
229126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
229226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
229326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT == check) {
229426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return true;
229526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
229626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
229726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
229826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
229926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
230026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return false;
230126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
230226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
230326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
230426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
230526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
230626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
230726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const {
230826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() != check);
230926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
231026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
231126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
231226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
231326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT->segment() == check) {
231426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return ptT;
231526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
231626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
231726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
231826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
231926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
232026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return nullptr;
232126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
232226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
232326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
232426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
232526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
232626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
232754359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const {
232854359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
232954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* next = this;
233054359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
233154359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
233254359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* checkPtT = this->fNext;
233354359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* innerPtT = checkPtT;
233454359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
233554359294a7c9dc54802d512a5d891a35c1663392caryclark                innerPtT = innerPtT->fNext;
233654359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkPtT == innerPtT) {
233754359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (report) {
233854359294a7c9dc54802d512a5d891a35c1663392caryclark                        SkDebugf("*** bad ptT loop ***\n");
233954359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
234054359294a7c9dc54802d512a5d891a35c1663392caryclark                    return loop;
234154359294a7c9dc54802d512a5d891a35c1663392caryclark                }
23424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
23434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
234426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // there's nothing wrong with extremely large loop counts -- but this may appear to hang
234526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // by taking a very long time to figure out that no loop entry is a duplicate
234626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // -- and it's likely that a large loop count is indicative of a bug somewhere
234726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (++loop > 1000) {
234826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("*** loop count exceeds 1000 ***\n");
234926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return 1000;
235026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
235154359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = next->fNext) && next != this);
235254359294a7c9dc54802d512a5d891a35c1663392caryclark    return 0;
235354359294a7c9dc54802d512a5d891a35c1663392caryclark}
235454359294a7c9dc54802d512a5d891a35c1663392caryclark
235554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const {
235655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
235755888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
235855888e44171ffd48b591d19256884a969fe4da17caryclark        return;
235955888e44171ffd48b591d19256884a969fe4da17caryclark    }
236055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
236154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
23624e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark    SkOpGlobalState::Phase phase = contour()->globalState()->phase();
23634e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark    if (phase == SkOpGlobalState::kIntersecting
23644e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark            || phase == SkOpGlobalState::kFixWinding) {
236554359294a7c9dc54802d512a5d891a35c1663392caryclark        return;
23664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
236754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext);
236854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext != this);
236954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext->fNext);
237054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(debugLoopLimit(false) == 0);
23714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
23724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
23731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
23741049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) {
23751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (num == (int) num) {
23761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%d", (int) num);
23771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    } else {
23781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkString str;
23791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.printf("%1.9g", num);
23801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        int width = (int) str.size();
23811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* cStr = str.c_str();
23821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        while (cStr[width - 1] == '0') {
23831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            --width;
23841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
23851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.resize(width);
23861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%sf", str.c_str());
23871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
23881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
23891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
23901049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) {
23911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    for (int index = 0; index < count; ++index) {
23921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fX);
23931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf(", ");
23941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fY);
23951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (index + 1 < count) {
23961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf(", ");
23971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
23981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
23991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
24001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
24011049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) {
24021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    uint8_t verb;
24031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPoint pts[4];
24041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
24051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        switch (verb) {
24061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kMove_Verb:
24071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.moveTo(", pathName);
24081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[0], 1);
24091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
24101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                continue;
24111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kLine_Verb:
24121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.lineTo(", pathName);
24131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 1);
24141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
24151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
24161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kQuad_Verb:
24171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.quadTo(", pathName);
24181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
24191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
24201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
24211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kConic_Verb:
24221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.conicTo(", pathName);
24231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
24241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(", %1.9gf);\n", iter.conicWeight());
24251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
24261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kCubic_Verb:
24271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.cubicTo(", pathName);
24281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 3);
24291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
24301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
24311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kClose_Verb:
24321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.close();\n", pathName);
24331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
24341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            default:
24351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDEBUGFAIL("bad verb");
24361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                return;
24371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
24381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
24391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
24401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
24411049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = {
24421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kWinding_FillType",
24431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kEvenOdd_FillType",
24441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseWinding_FillType",
24451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseEvenOdd_FillType"
24461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
24471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
24481049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) {
24491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::RawIter iter(path);
24501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0
24511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION
245296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0;
24531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (rectCount > 0) {
24541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkRect> rects;
24551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkPath::Direction> directions;
24561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        rects.setCount(rectCount);
24571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        directions.setCount(rectCount);
24581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        path.rectContours(rects.begin(), directions.begin());
24591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        for (int contour = 0; contour < rectCount; ++contour) {
24601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            const SkRect& rect = rects[contour];
24611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
24621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
24631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
24641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
24651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        return;
24661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
24671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif
24681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::FillType fillType = path.getFillType();
24691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType);
24701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (includeDeclaration) {
24711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("    SkPath %s;\n", name);
24721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
24731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]);
24741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    iter.setPath(path);
24751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    showPathContours(iter, name);
24761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
2477