SkPathOpsDebug.cpp revision 59d5a0e3f560da40e0ae7036a01d7d58ce3718d8
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"
111326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkOSFile.h"
1202802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h"
131b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h"
1454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h"
1554359294a7c9dc54802d512a5d891a35c1663392caryclark
16918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY
171326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gDumpOp;  // set to true to write op to file before a crash
181326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVerifyOp;  // set to true to compare result against regions
191326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif
201326068147ee60de138061a3fc1157fcfd5d017bcaryclark
2159d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clarkbool SkPathOpsDebug::gRunFail;  // set to true to check for success on tests known to fail
221326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVeryVerbose;  // set to true to run extensive checking tests
231326068147ee60de138061a3fc1157fcfd5d017bcaryclark
2430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_IF
2530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_IF(cond, coin) \
26ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark         do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false)
2730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
2830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_WITH_NULL_IF
2930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_WITH_NULL_IF(cond, span) \
30ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark         do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, span); } while (false)
3130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
3230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef RETURN_FALSE_IF
3330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define RETURN_FALSE_IF(cond, span) \
34ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark         do { if (cond) log->record(SkPathOpsDebug::kReturnFalse_Glitch, span); \
35ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark         } while (false)
3630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
3755888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans;
3826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
39624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
40624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
41624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount;
42624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
43624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
44624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP
45624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
46624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
47624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
50570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org
52fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0;
53fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0;
54570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
5554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray,
5654359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* span) {
574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int index = 0; index < chaseArray.count(); ++index) {
5854359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* entry = chaseArray[index];
594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (entry == span) {
604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return true;
614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return false;
644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
66ff11428526843d3e03feb6843bd21f2d80536415Cary Clark
67ff11428526843d3e03feb6843bd21f2d80536415Cary Clark#if DEBUG_ACTIVE_SPANS
68ff11428526843d3e03feb6843bd21f2d80536415Cary ClarkSkString SkPathOpsDebug::gActiveSpans;
69ff11428526843d3e03feb6843bd21f2d80536415Cary Clark#endif
7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
71ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
73ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumChangedDict;
74ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumVisitedDict;
75ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
76ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic const int kGlitchType_Count = SkPathOpsDebug::kUnalignedTail_Glitch + 1;
7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
7826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch {
7926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fBase;
8026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fSuspect;
8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* fSegment;
8255888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* fOppSegment;
8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fCoinSpan;
8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fEndSpan;
8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppSpan;
8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppEndSpan;
8755888e44171ffd48b591d19256884a969fe4da17caryclark    double fStartT;
8855888e44171ffd48b591d19256884a969fe4da17caryclark    double fEndT;
8955888e44171ffd48b591d19256884a969fe4da17caryclark    double fOppStartT;
9055888e44171ffd48b591d19256884a969fe4da17caryclark    double fOppEndT;
9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkPoint fPt;
92ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkPathOpsDebug::GlitchType fType;
93ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
94ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void dumpType() const;
9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog {
98ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void init(const SkOpGlobalState* state) {
99ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fGlobalState = state;
100ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
101ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
102ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SpanGlitch* recordCommon(GlitchType type) {
10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = fGlitches.push();
10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = nullptr;
10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = nullptr;
10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = nullptr;
10755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSegment = nullptr;
10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = nullptr;
10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = nullptr;
11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = nullptr;
11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = nullptr;
11255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = SK_ScalarNaN;
11355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndT = SK_ScalarNaN;
11455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppStartT = SK_ScalarNaN;
11555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndT = SK_ScalarNaN;
11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN };
11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fType = type;
11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return glitch;
11926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
121ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSpanBase* base,
12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* suspect = NULL) {
123ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = suspect;
12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
128ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSpanBase* base,
12955888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* ptT) {
130ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
13155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = base;
13255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = ptT;
13355888e44171ffd48b591d19256884a969fe4da17caryclark    }
13455888e44171ffd48b591d19256884a969fe4da17caryclark
135ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkCoincidentSpans* coin,
13655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkCoincidentSpans* opp = NULL) {
137ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
13855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
13955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
14055888e44171ffd48b591d19256884a969fe4da17caryclark        if (opp) {
14155888e44171ffd48b591d19256884a969fe4da17caryclark            glitch->fOppSpan = opp->coinPtTStart();
14255888e44171ffd48b591d19256884a969fe4da17caryclark            glitch->fOppEndSpan = opp->coinPtTEnd();
14355888e44171ffd48b591d19256884a969fe4da17caryclark        }
14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
146ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSpanBase* base,
14726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* seg, double t, SkPoint pt) {
148ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = seg;
15155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
155ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSpanBase* base, double t,
15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkPoint pt) {
157ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
15955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
163ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkCoincidentSpans* coin,
16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* coinSpan, const SkOpPtT* endSpan) {
165ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
16655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
16755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = endSpan;
16955888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSpan = coinSpan;
17055888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndSpan = endSpan;
17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
17226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
173ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkCoincidentSpans* coin,
17455888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpanBase* base) {
175ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
17655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = base;
17755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
17855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = coin->coinPtTEnd();
17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
181ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpPtT* ptTS, const SkOpPtT* ptTE,
18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) {
183ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = ptTS;
18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = ptTE;
18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = oPtTS;
18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = oPtTE;
18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
190ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSegment* seg, double startT,
19155888e44171ffd48b591d19256884a969fe4da17caryclark            double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) {
192ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
19355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
19455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = startT;
19555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndT = endT;
19655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppSegment = oppSeg;
19755888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppStartT = oppStartT;
19855888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fOppEndT = oppEndT;
19955888e44171ffd48b591d19256884a969fe4da17caryclark    }
20055888e44171ffd48b591d19256884a969fe4da17caryclark
201ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSegment* seg,
20255888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpan* span) {
203ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
20455888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
20555888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = span;
20655888e44171ffd48b591d19256884a969fe4da17caryclark    }
20755888e44171ffd48b591d19256884a969fe4da17caryclark
208ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, double t, const SkOpSpanBase* span) {
209ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
21055888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fStartT = t;
21155888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fBase = span;
21255888e44171ffd48b591d19256884a969fe4da17caryclark    }
21355888e44171ffd48b591d19256884a969fe4da17caryclark
214ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkOpSegment* seg) {
215ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
21655888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fSegment = seg;
21755888e44171ffd48b591d19256884a969fe4da17caryclark    }
21855888e44171ffd48b591d19256884a969fe4da17caryclark
219ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    void record(GlitchType type, const SkCoincidentSpans* coin,
22055888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* ptT) {
221ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SpanGlitch* glitch = recordCommon(type);
22255888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fCoinSpan = coin->coinPtTStart();
22355888e44171ffd48b591d19256884a969fe4da17caryclark        glitch->fEndSpan = ptT;
22455888e44171ffd48b591d19256884a969fe4da17caryclark    }
22555888e44171ffd48b591d19256884a969fe4da17caryclark
22626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkTDArray<SpanGlitch> fGlitches;
227ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpGlobalState* fGlobalState;
22826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
229ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
230ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
231ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const SkPathOpsDebug::CoinDict& dict) {
232ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    int count = dict.fDict.count();
233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    for (int index = 0; index < count; ++index) {
234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        this->add(dict.fDict[index]);
235ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
236ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
237ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
238ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const CoinDictEntry& key) {
239ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    int count = fDict.count();
240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    for (int index = 0; index < count; ++index) {
241ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        CoinDictEntry* entry = &fDict[index];
242ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (entry->fIteration == key.fIteration && entry->fLineNumber == key.fLineNumber) {
243ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkASSERT(!strcmp(entry->fFunctionName, key.fFunctionName));
244ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (entry->fGlitchType == kUninitialized_Glitch) {
245ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                entry->fGlitchType = key.fGlitchType;
246ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
247ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
248ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
249ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
250ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    *fDict.append() = key;
251ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
253ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
254ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
256ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void missing_coincidence(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) {
257ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpContour* contour = contourList;
258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    // bool result = false;
259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
260ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        /* result |= */ contour->debugMissingCoincidence(glitches);
261ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((contour = contour->next()));
262ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
263ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
264ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
265ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_multiples(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) {
266ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpContour* contour = contourList;
267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (contour->debugMoveMultiples(glitches), false) {
269ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
270ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
271ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((contour = contour->next()));
272ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_nearby(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) {
276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpContour* contour = contourList;
277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
278ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        contour->debugMoveNearby(glitches);
279ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((contour = contour->next()));
280ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
284ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
285ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToCoinChangedDict() {
287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE
289e6522ea38fa3bcfdf2d718ea5ad898b3b3d46e00caryclark    SkPathOpsDebug::CheckHealth(fContourHead);
290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    // see if next coincident operation makes a change; if so, record it
292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkPathOpsDebug::GlitchLog glitches;
293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const char* funcName = fCoinDictEntry.fFunctionName;
294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!strcmp("calc_angles", funcName)) {
295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        ;
296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("missing_coincidence", funcName)) {
297ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        missing_coincidence(&glitches, fContourHead);
298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("move_multiples", funcName)) {
299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        move_multiples(&glitches, fContourHead);
300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("move_nearby", funcName)) {
301ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        move_nearby(&glitches, fContourHead);
302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("addExpanded", funcName)) {
303ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugAddExpanded(&glitches);
304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("addMissing", funcName)) {
305ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        bool added;
306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugAddMissing(&glitches, &added);
307ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("addEndMovedSpans", funcName)) {
308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugAddEndMovedSpans(&glitches);
309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("correctEnds", funcName)) {
310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugCorrectEnds(&glitches);
311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("expand", funcName)) {
312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugExpand(&glitches);
313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("findOverlaps", funcName)) {
314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        ;
315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("mark", funcName)) {
316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoincidence->debugMark(&glitches);
317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else if (!strcmp("apply", funcName)) {
318ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        ;
319ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } else {
320ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkASSERT(0);   // add missing case
321ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
322ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (glitches.fGlitches.count()) {
323ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        fCoinDictEntry.fGlitchType = glitches.fGlitches[0].fType;
324ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
325ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    fCoinChangedDict.add(fCoinDictEntry);
326ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
32755888e44171ffd48b591d19256884a969fe4da17caryclark#endif
32826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
32955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) {
33055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS
331ff11428526843d3e03feb6843bd21f2d80536415Cary Clark    SkString str;
33255888e44171ffd48b591d19256884a969fe4da17caryclark    SkOpContour* contour = contourList;
33355888e44171ffd48b591d19256884a969fe4da17caryclark    do {
334ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        contour->debugShowActiveSpans(&str);
33555888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((contour = contour->next()));
336ff11428526843d3e03feb6843bd21f2d80536415Cary Clark    if (!gActiveSpans.equals(str)) {
337ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        const char* s = str.c_str();
338ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        const char* end;
339ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        while ((end = strchr(s, '\n'))) {
340ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            SkDebugf("%.*s", end - s + 1, s);
341ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            s = end + 1;
342ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        }
343ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        gActiveSpans.set(str);
344ff11428526843d3e03feb6843bd21f2d80536415Cary Clark    }
34555888e44171ffd48b591d19256884a969fe4da17caryclark#endif
34655888e44171ffd48b591d19256884a969fe4da17caryclark}
34755888e44171ffd48b591d19256884a969fe4da17caryclark
348ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE || DEBUG_COIN
349ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList) {
35055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
35155888e44171ffd48b591d19256884a969fe4da17caryclark    contourList->globalState()->debugSetCheckHealth(true);
352ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
353ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    GlitchLog glitches;
35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpContour* contour = contourList;
35626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpCoincidence* coincidence = contour->globalState()->coincidence();
357ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincidence->debugCheckValid(&glitches); // don't call validate; spans may be inconsistent
35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
359ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        contour->debugCheckHealth(&glitches);
360ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        contour->debugMissingCoincidence(&glitches);
36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((contour = contour->next()));
36281a478ca6c36aac3e53ce0373a281ac8940f4780caryclark    bool added;
363ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincidence->debugAddMissing(&glitches, &added);
364ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincidence->debugExpand(&glitches);
365ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincidence->debugAddExpanded(&glitches);
366ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincidence->debugMark(&glitches);
36726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    unsigned mask = 0;
36826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < glitches.fGlitches.count(); ++index) {
36926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SpanGlitch& glitch = glitches.fGlitches[index];
37026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        mask |= 1 << glitch.fType;
37126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
37226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < kGlitchType_Count; ++index) {
37326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(mask & (1 << index) ? "x" : "-");
37426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
375ff11428526843d3e03feb6843bd21f2d80536415Cary Clark    SkDebugf(" %s\n", contourList->globalState()->debugCoinDictEntry().fFunctionName);
37655888e44171ffd48b591d19256884a969fe4da17caryclark    for (int index = 0; index < glitches.fGlitches.count(); ++index) {
37755888e44171ffd48b591d19256884a969fe4da17caryclark        const SpanGlitch& glitch = glitches.fGlitches[index];
37855888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf("%02d: ", index);
37955888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fBase) {
3808016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(),
3818016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                    glitch.fBase->debugID());
38255888e44171ffd48b591d19256884a969fe4da17caryclark        }
38355888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fSuspect) {
3848016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(),
3858016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                    glitch.fSuspect->debugID());
38655888e44171ffd48b591d19256884a969fe4da17caryclark        }
38755888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fSegment) {
38855888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" segment=%d", glitch.fSegment->debugID());
38955888e44171ffd48b591d19256884a969fe4da17caryclark        }
39055888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fCoinSpan) {
3918016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(),
3928016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                    glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID());
39355888e44171ffd48b591d19256884a969fe4da17caryclark        }
39455888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fEndSpan) {
39555888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID());
39655888e44171ffd48b591d19256884a969fe4da17caryclark        }
39755888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppSpan) {
3988016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(),
3998016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                    glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID());
40055888e44171ffd48b591d19256884a969fe4da17caryclark        }
40155888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppEndSpan) {
40255888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID());
40355888e44171ffd48b591d19256884a969fe4da17caryclark        }
40455888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fStartT)) {
40555888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" startT=%g", glitch.fStartT);
40655888e44171ffd48b591d19256884a969fe4da17caryclark        }
40755888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fEndT)) {
40855888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" endT=%g", glitch.fEndT);
40955888e44171ffd48b591d19256884a969fe4da17caryclark        }
41055888e44171ffd48b591d19256884a969fe4da17caryclark        if (glitch.fOppSegment) {
41155888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" segment=%d", glitch.fOppSegment->debugID());
41255888e44171ffd48b591d19256884a969fe4da17caryclark        }
41355888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fOppStartT)) {
41455888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppStartT=%g", glitch.fOppStartT);
41555888e44171ffd48b591d19256884a969fe4da17caryclark        }
41655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fOppEndT)) {
41755888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" oppEndT=%g", glitch.fOppEndT);
41855888e44171ffd48b591d19256884a969fe4da17caryclark        }
41955888e44171ffd48b591d19256884a969fe4da17caryclark        if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) {
42055888e44171ffd48b591d19256884a969fe4da17caryclark            SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY);
42155888e44171ffd48b591d19256884a969fe4da17caryclark        }
422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        DumpGlitchType(glitch.fType);
42355888e44171ffd48b591d19256884a969fe4da17caryclark        SkDebugf("\n");
42455888e44171ffd48b591d19256884a969fe4da17caryclark    }
425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE
42655888e44171ffd48b591d19256884a969fe4da17caryclark    contourList->globalState()->debugSetCheckHealth(false);
427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
4286c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if 01 && DEBUG_ACTIVE_SPANS
429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark//    SkDebugf("active after %s:\n", id);
43055888e44171ffd48b591d19256884a969fe4da17caryclark    ShowActiveSpans(contourList);
43155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
43255888e44171ffd48b591d19256884a969fe4da17caryclark#endif
43326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
43426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
4354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::DumpGlitchType(GlitchType glitchType) {
438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    switch (glitchType) {
439ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break;
440ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break;
441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break;
442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break;
443ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break;
444ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break;
445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break;
446ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break;
447ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break;
448ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break;
449ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break;
450ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break;
451ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break;
452ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kCorrectEnd_Glitch: SkDebugf(" CorrectEnd"); break;
453ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break;
454ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break;
455ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kFail_Glitch: SkDebugf(" Fail"); break;
456ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break;
457ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break;
458ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break;
459ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break;
460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break;
461ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break;
462ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMissingDone_Glitch: SkDebugf(" MissingDone"); break;
463ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break;
464ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break;
465ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break;
466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break;
467ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break;
468ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break;
469ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break;
470ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break;
471ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break;
472ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kReturnFalse_Glitch: SkDebugf(" ReturnFalse"); break;
473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kUnaligned_Glitch: SkDebugf(" Unaligned"); break;
474ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break;
475ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break;
476ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        case kUninitialized_Glitch: break;
477ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        default: SkASSERT(0);
478ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
479ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
480ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE
483570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
48407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    size_t len = strlen(str);
48507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool num = false;
48607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    for (size_t idx = 0; idx < len; ++idx) {
48707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (num && str[idx] == 'e') {
48807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (len + 2 >= bufferLen) {
48907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                return;
49007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
49107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            memmove(&str[idx + 2], &str[idx + 1], len - idx);
49207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx] = '*';
49307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx + 1] = '^';
49407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++len;
49507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
49607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        num = str[idx] >= '0' && str[idx] <= '9';
49707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
49807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
49907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
500570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) {
50107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
50207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
50307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
504570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) {
50507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (wind == SK_MinS32) {
50607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("?");
50707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
50807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%d", wind);
50907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
51007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
51154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif //  defined SK_DEBUG || !FORCE_RELEASE
51254359294a7c9dc54802d512a5d891a35c1663392caryclark
513a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
51407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME
515385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; }
516cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
517385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); }
518a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
519570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) {
52007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    char* num = test + strlen(test);
52107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    while (num[-1] >= '0' && num[-1] <= '9') {
52207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        --num;
52307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
52407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (num[0] == '\0') {
52507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
52607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
52707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    int dec = atoi(num);
52807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (dec == 0) {
52907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
53007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
53107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    ++dec;
53207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec);
533a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com}
534a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif
535570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
5361049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) {
5371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName);
5381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (strcmp("skphealth_com76", functionName) == 0) {
5391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("found it\n");
5401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
5411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
5421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
5431049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = {
5441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kDifference_SkPathOp",
5451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kIntersect_SkPathOp",
5461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kUnion_SkPathOp",
54755888e44171ffd48b591d19256884a969fe4da17caryclark    "kXOR_PathOp",
5481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kReverseDifference_SkPathOp",
5491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
5501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
55103b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) {
55203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark    return gOpStrs[op];
55303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark}
55403b03cad01628146bbb8d4f33c073bd0c77ee558caryclark
5551049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) {
5561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]);
5571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("}\n");
5581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
5591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
560086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex);
5611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
5621049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
5631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* testName) {
5641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkAutoMutexAcquire ac(gTestMutex);
5651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_function_header(testName);
5661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(a, "path", true);
5671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(b, "pathB", true);
5681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_op(shapeOp, "path", "pathB");
5694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
5704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
57127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h"
57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h"
57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h"
57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
577ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSK_DECLARE_STATIC_MUTEX(gCoinDictMutex);
578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToGlobalCoinDicts() {
580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkAutoMutexAcquire ac(&gCoinDictMutex);
581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict);
582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict);
583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt,
58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkIntersectionHelper& wn) {
59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index;
59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) {
59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = i->debugLoopCount(looper);
59626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = wt.segment()->verb();
59726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb();
59826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8);
59926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(),
60026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint));
60126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(),
60226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint));
60326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = wt.weight();
60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = wn.weight();
60526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
60626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    i->debugResetLoopCount();
60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
60826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) {
61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) {
61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = local->fDebugLoopCount[index];
61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2];
61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1];
61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4],
61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                sizeof(SkPoint) * 8);
61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2];
62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1];
62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    local->debugResetLoopCounts();
62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) {
62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!verb) {
62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* verbs[] = { "", "line", "quad", "conic", "cubic" };
63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("%s: {{", verbs[verb]);
63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int ptCount = SkPathOpsVerbToPoints(verb);
63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index <= ptCount; ++index) {
63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint::Dump((&pts)[index]);
63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (index < ptCount - 1) {
63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf(", ");
63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}");
63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (weight != 1) {
64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(", ");
64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (weight == floorf(weight)) {
64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%.0f", weight);
64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } else {
64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%1.9gf", weight);
64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}\n");
64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() {
65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* loops[] = { "iterations", "coinChecks", "perpCalcs" };
65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("\n");
65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]);
65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4],
65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2]);
65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4],
65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2 + 1]);
65926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() {
66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb));
66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts));
66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight));
66726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
66927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
67059d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clarkbool SkOpGlobalState::DebugRunFail() {
67159d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark    return SkPathOpsDebug::gRunFail;
67259d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark}
67359d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark
674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this is const so it can be called by const methods that overwise don't alter state
675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE || DEBUG_COIN
676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugSetPhase(const char* funcName  DEBUG_COIN_DECLARE_PARAMS()) const {
677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    auto writable = const_cast<SkOpGlobalState*>(this);
678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE
679ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    writable->setPhase(phase);
680ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
681ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
682ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkPathOpsDebug::CoinDictEntry* entry = &writable->fCoinDictEntry;
683ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    writable->fPreviousFuncName = entry->fFunctionName;
684ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    entry->fIteration = iteration;
685ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    entry->fLineNumber = lineNo;
686ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    entry->fGlitchType = SkPathOpsDebug::kUninitialized_Glitch;
687ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    entry->fFunctionName = funcName;
688ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    writable->fCoinVisitedDict.add(*entry);
689ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    writable->debugAddToCoinChangedDict();
690ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
691ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
692ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif
693ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
69426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
69526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) {
69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    fDebugLoopCount[index]++;
69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
69926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const {
70026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return fDebugLoopCount[index];
70126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
70226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
70326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() {
70426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
70526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
70626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
70726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
708a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark#include "SkPathOpsConic.h"
709624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h"
710624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
711624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const {
712624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDCubic cubic;
713624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[0] = fPts[0];
714624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2] = fPts[1];
715624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[3] = fPts[2];
716624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3;
717624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3;
718624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3;
719624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3;
720624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return cubic;
721624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
722624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
723a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDQuad::debugSet(const SkDPoint* pts) {
724a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    memcpy(fPts, pts, sizeof(fPts));
725a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    SkDEBUGCODE(fDebugGlobalState = nullptr);
726a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark}
727a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark
728a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDCubic::debugSet(const SkDPoint* pts) {
729a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    memcpy(fPts, pts, sizeof(fPts));
730a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    SkDEBUGCODE(fDebugGlobalState = nullptr);
731a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark}
732a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark
733a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDConic::debugSet(const SkDPoint* pts, SkScalar weight) {
734a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    fPts.debugSet(pts);
735a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    fWeight = weight;
736a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark}
737a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark
738ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() {
739ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    fLeft = fTop = fRight = fBottom = SK_ScalarNaN;
740ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark}
741ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark
7424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h"
743570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h"
744570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
745ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
74655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT()
747ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* SkOpSegment::debugAddT(double t, SkPathOpsDebug::GlitchLog* log) const {
74855888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
74955888e44171ffd48b591d19256884a969fe4da17caryclark    SkPoint pt = this->ptAtT(t);
75055888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* span = &fHead;
75126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
75255888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* result = span->ptT();
75329b2563afb1677515739f1d24fb27733626eca92caryclark        if (t == result->fT || this->match(result, this, t, pt)) {
75455888e44171ffd48b591d19256884a969fe4da17caryclark//             span->bumpSpanAdds();
755ef4f32ac858825dc443cfe4739ea878fb0bf550fcaryclark             return result;
75655888e44171ffd48b591d19256884a969fe4da17caryclark        }
75755888e44171ffd48b591d19256884a969fe4da17caryclark        if (t < result->fT) {
75855888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSpan* prev = result->span()->prev();
75930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            FAIL_WITH_NULL_IF(!prev, span);
76029b2563afb1677515739f1d24fb27733626eca92caryclark            // marks in global state that new op span has been allocated
76129b2563afb1677515739f1d24fb27733626eca92caryclark            this->globalState()->setAllocatedOpSpan();
76255888e44171ffd48b591d19256884a969fe4da17caryclark//             span->init(this, prev, t, pt);
76355888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
76455888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T
76555888e44171ffd48b591d19256884a969fe4da17caryclark//             SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t,
76655888e44171ffd48b591d19256884a969fe4da17caryclark//                     span->segment()->debugID(), span->debugID());
76755888e44171ffd48b591d19256884a969fe4da17caryclark// #endif
76855888e44171ffd48b591d19256884a969fe4da17caryclark//             span->bumpSpanAdds();
76955888e44171ffd48b591d19256884a969fe4da17caryclark            return nullptr;
77055888e44171ffd48b591d19256884a969fe4da17caryclark        }
77130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        FAIL_WITH_NULL_IF(span != &fTail, span);
77255888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((span = span->upCast()->next()));
77355888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(0);
77429b2563afb1677515739f1d24fb27733626eca92caryclark    return nullptr;  // we never get here, but need this to satisfy compiler
77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const {
78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* base = &fHead;
78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* span;
78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* angle = base->fromAngle();
78455888e44171ffd48b591d19256884a969fe4da17caryclark        if (angle && angle->debugCheckCoincidence()) {
78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (base->final()) {
78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark             break;
78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        span = base->upCast();
79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        angle = span->toAngle();
79255888e44171ffd48b591d19256884a969fe4da17caryclark        if (angle && angle->debugCheckCoincidence()) {
79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((base = span->next()));
79626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
79726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
79826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
799ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence
801ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugCheckHealth(SkPathOpsDebug::GlitchLog* glitches) const {
802ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    debugMoveMultiples(glitches);
803ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    debugMoveNearby(glitches);
804ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    debugMissingCoincidence(glitches);
80555888e44171ffd48b591d19256884a969fe4da17caryclark}
80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
80755888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll()
808ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const {
80955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpan* span = &fHead;
81055888e44171ffd48b591d19256884a969fe4da17caryclark    do {
811ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        this->debugClearOne(span, glitches);
81255888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((span = span->next()->upCastable()));
813ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->globalState()->coincidence()->debugRelease(glitches, this);
81426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
81526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
81655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne()
817ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const {
818ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (span->windValue()) glitches->record(SkPathOpsDebug::kCollapsedWindValue_Glitch, span);
819ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (span->oppValue()) glitches->record(SkPathOpsDebug::kCollapsedOppValue_Glitch, span);
820ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!span->done()) glitches->record(SkPathOpsDebug::kCollapsedDone_Glitch, span);
82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
82226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
82326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
82454359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() {
82596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpAngle* result = nullptr;
82654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* span = this->head();
82754359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
82854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->toAngle()) {
829dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!result);
83054359294a7c9dc54802d512a5d891a35c1663392caryclark            result = span->toAngle();
831dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
83254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((span = span->next()->upCastable()));
833dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkASSERT(result);
834dac1d17027dcaa5596885a9f333979418b35001ccaryclark    return result;
835dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
836dac1d17027dcaa5596885a9f333979418b35001ccaryclark
837ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
83855888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited
83955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) {
84055888e44171ffd48b591d19256884a969fe4da17caryclark    // reset visited flag back to false
84155888e44171ffd48b591d19256884a969fe4da17caryclark    do {
84255888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
84355888e44171ffd48b591d19256884a969fe4da17caryclark        while ((ptT = ptT->next()) != stopPtT) {
84455888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* opp = ptT->segment();
84555888e44171ffd48b591d19256884a969fe4da17caryclark            opp->resetDebugVisited();
84655888e44171ffd48b591d19256884a969fe4da17caryclark        }
84755888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!span->final() && (span = span->upCast()->next()));
84855888e44171ffd48b591d19256884a969fe4da17caryclark}
84955888e44171ffd48b591d19256884a969fe4da17caryclark#endif
85055888e44171ffd48b591d19256884a969fe4da17caryclark
851ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
85255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence()
85355888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves
85455888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear
85555888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed
85655888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given
85755888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C:
85855888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near
85955888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C.
86055888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2,
86155888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B.
862ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const {
86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (this->done()) {
86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* prior = nullptr;
86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* spanBase = &fHead;
86855888e44171ffd48b591d19256884a969fe4da17caryclark//    bool result = false;
86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(ptT->span() == spanBase);
87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((ptT = ptT->next()) != spanStopPtT) {
87326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT->deleted()) {
87426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
87655888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpSegment* opp = ptT->span()->segment();
87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (opp->done()) {
87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
88155888e44171ffd48b591d19256884a969fe4da17caryclark            if (!opp->debugVisited()) {
88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (spanBase == &fHead) {
88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
88755888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() == this) {
88855888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
88955888e44171ffd48b591d19256884a969fe4da17caryclark            }
89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* span = spanBase->upCastable();
89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // FIXME?: this assumes that if the opposite segment is coincident then no more
89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // coincidence needs to be detected. This may not be true.
89355888e44171ffd48b591d19256884a969fe4da17caryclark            if (span && span->segment() != opp && span->containsCoincidence(opp)) {  // debug has additional condition since it may be called before inner duplicate points have been deleted
89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
89526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
89655888e44171ffd48b591d19256884a969fe4da17caryclark            if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) {  // debug has additional condition since it may be called before inner duplicate points have been deleted
89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
89855888e44171ffd48b591d19256884a969fe4da17caryclark            }
89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* priorPtT = nullptr, * priorStopPtT;
90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find prior span containing opp segment
90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* priorOpp = nullptr;
90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* priorTest = spanBase->prev();
90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while (!priorOpp && priorTest) {
90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorStopPtT = priorPtT = priorTest->ptT();
90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((priorPtT = priorPtT->next()) != priorStopPtT) {
90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (priorPtT->deleted()) {
90726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        continue;
90826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
909ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    const SkOpSegment* segment = priorPtT->span()->segment();
91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (segment == opp) {
91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        prior = priorTest;
91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        priorOpp = opp;
91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        break;
91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
91626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorTest = priorTest->prev();
91726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
91826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!priorOpp) {
91926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
92026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
92155888e44171ffd48b591d19256884a969fe4da17caryclark            if (priorPtT == ptT) {
92255888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
92355888e44171ffd48b591d19256884a969fe4da17caryclark            }
92426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppStart = prior->ptT();
92526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppEnd = spanBase->ptT();
92626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool swapped = priorPtT->fT > ptT->fT;
92726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
92826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
92926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(oppStart, oppEnd);
93026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
93155888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpCoincidence* coincidence = this->globalState()->coincidence();
93255888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT();
93355888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootPtT = ptT->span()->ptT();
93455888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootOppStart = oppStart->span()->ptT();
93555888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* rootOppEnd = oppEnd->span()->ptT();
93655888e44171ffd48b591d19256884a969fe4da17caryclark            if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) {
93726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                goto swapBack;
93826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
93955888e44171ffd48b591d19256884a969fe4da17caryclark            if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) {
94055888e44171ffd48b591d19256884a969fe4da17caryclark            // mark coincidence
94130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE
94255888e44171ffd48b591d19256884a969fe4da17caryclark//                 SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__,
94355888e44171ffd48b591d19256884a969fe4da17caryclark//                         rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(),
94455888e44171ffd48b591d19256884a969fe4da17caryclark//                         rootOppEnd->debugID());
94555888e44171ffd48b591d19256884a969fe4da17caryclark#endif
946ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log->record(SkPathOpsDebug::kMissingCoin_Glitch, priorPtT, ptT, oppStart, oppEnd);
94755888e44171ffd48b591d19256884a969fe4da17caryclark                //   coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd);
94855888e44171ffd48b591d19256884a969fe4da17caryclark                // }
94955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
950d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark//                SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd);
95155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
95255888e44171ffd48b591d19256884a969fe4da17caryclark                // result = true;
95326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
95426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    swapBack:
95526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
95626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
95726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next()));
96055888e44171ffd48b591d19256884a969fe4da17caryclark    DebugClearVisited(&fHead);
96155888e44171ffd48b591d19256884a969fe4da17caryclark    return;
96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
96455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples()
96555888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed
966ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const {
96755888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* test = &fHead;
96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        int addCount = test->spanAddsCount();
971ff11428526843d3e03feb6843bd21f2d80536415Cary Clark//        SkASSERT(addCount >= 1);
972ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        if (addCount <= 1) {
97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* startPtT = test->ptT();
97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* testPtT = startPtT;
97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {  // iterate through all spans associated with start
97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppSpan = testPtT->span();
97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->spanAddsCount() == addCount) {
98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->deleted()) {
98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* oppSegment = oppSpan->segment();
98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSegment == this) {
98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find range of spans to consider merging
99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppPrev = oppSpan;
99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppFirst = oppSpan;
99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppPrev = oppPrev->prev())) {
99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppPrev->t(), oppSpan->t())) {
99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->spanAddsCount() == addCount) {
99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->deleted()) {
100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppFirst = oppPrev;
100326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
100426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppNext = oppSpan;
100526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppLast = oppSpan;
100626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) {
100726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppNext->t(), oppSpan->t())) {
100826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
100926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
101026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->spanAddsCount() == addCount) {
101126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
101226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
101326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->deleted()) {
101426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
101526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
101626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppLast = oppNext;
101726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
101826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppFirst == oppLast) {
101926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
102026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
102126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppTest = oppFirst;
102226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            do {
102326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppTest == oppSpan) {
102426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
102526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
102626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // check to see if the candidate meets specific criteria:
102726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // it contains spans of segments in test's loop but not including 'this'
102826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppStartPtT = oppTest->ptT();
102926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppPtT = oppStartPtT;
103026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((oppPtT = oppPtT->next()) != oppStartPtT) {
103126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpSegment* oppPtTSegment = oppPtT->segment();
103226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (oppPtTSegment == this) {
103326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        goto tryNextSpan;
103426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
103526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpPtT* matchPtT = startPtT;
103626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    do {
103726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        if (matchPtT->segment() == oppPtTSegment) {
103826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            goto foundMatch;
103926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        }
104026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } while ((matchPtT = matchPtT->next()) != startPtT);
104126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto tryNextSpan;
104226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            foundMatch:  // merge oppTest and oppSpan
104355888e44171ffd48b591d19256884a969fe4da17caryclark                    oppSegment->debugValidate();
1044ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    oppTest->debugMergeMatches(glitches, oppSpan);
1045ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    oppTest->debugAddOpp(glitches, oppSpan);
104655888e44171ffd48b591d19256884a969fe4da17caryclark                    oppSegment->debugValidate();
104726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto checkNextSpan;
104826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
104955888e44171ffd48b591d19256884a969fe4da17caryclark        tryNextSpan:
105026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                ;
105126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()));
105226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((testPtT = testPtT->next()) != startPtT);
105355888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan:
105426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ;
105526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((test = test->final() ? nullptr : test->upCast()->next()));
105655888e44171ffd48b591d19256884a969fe4da17caryclark   debugValidate();
105755888e44171ffd48b591d19256884a969fe4da17caryclark   return;
105826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
105926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
106055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby()
106155888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later.
1062ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const {
106355888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
106455888e44171ffd48b591d19256884a969fe4da17caryclark    // release undeleted spans pointing to this seg that are linked to the primary span
106555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSpanBase* spanBase = &fHead;
106626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
106755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = spanBase->ptT();
106855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* headPtT = ptT;
106955888e44171ffd48b591d19256884a969fe4da17caryclark        while ((ptT = ptT->next()) != headPtT) {
107055888e44171ffd48b591d19256884a969fe4da17caryclark              const SkOpSpanBase* test = ptT->span();
107155888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() == this && !ptT->deleted() && test != spanBase
107255888e44171ffd48b591d19256884a969fe4da17caryclark                    && test->ptT() == ptT) {
107355888e44171ffd48b591d19256884a969fe4da17caryclark                if (test->final()) {
107455888e44171ffd48b591d19256884a969fe4da17caryclark                    if (spanBase == &fHead) {
1075ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        glitches->record(SkPathOpsDebug::kMoveNearbyClearAll_Glitch, this);
107655888e44171ffd48b591d19256884a969fe4da17caryclark//                        return;
107755888e44171ffd48b591d19256884a969fe4da17caryclark                    }
1078ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    glitches->record(SkPathOpsDebug::kMoveNearbyReleaseFinal_Glitch, spanBase, ptT);
107955888e44171ffd48b591d19256884a969fe4da17caryclark                } else if (test->prev()) {
1080ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    glitches->record(SkPathOpsDebug::kMoveNearbyRelease_Glitch, test, headPtT);
108155888e44171ffd48b591d19256884a969fe4da17caryclark                }
108255888e44171ffd48b591d19256884a969fe4da17caryclark//                break;
108326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
108426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
108555888e44171ffd48b591d19256884a969fe4da17caryclark        spanBase = spanBase->upCast()->next();
108655888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!spanBase->final());
108755888e44171ffd48b591d19256884a969fe4da17caryclark
108855888e44171ffd48b591d19256884a969fe4da17caryclark    // This loop looks for adjacent spans which are near by
108955888e44171ffd48b591d19256884a969fe4da17caryclark    spanBase = &fHead;
109055888e44171ffd48b591d19256884a969fe4da17caryclark    do {  // iterate through all spans associated with start
109155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* test = spanBase->upCast()->next();
109255888e44171ffd48b591d19256884a969fe4da17caryclark        if (this->spansNearby(spanBase, test)) {
109355888e44171ffd48b591d19256884a969fe4da17caryclark            if (test->final()) {
109455888e44171ffd48b591d19256884a969fe4da17caryclark                if (spanBase->prev()) {
1095ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test);
109655888e44171ffd48b591d19256884a969fe4da17caryclark                } else {
1097ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    glitches->record(SkPathOpsDebug::kMoveNearbyClearAll2_Glitch, this);
109855888e44171ffd48b591d19256884a969fe4da17caryclark                    // return
109955888e44171ffd48b591d19256884a969fe4da17caryclark                }
110055888e44171ffd48b591d19256884a969fe4da17caryclark            } else {
1101ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                glitches->record(SkPathOpsDebug::kMoveNearbyMerge_Glitch, spanBase);
110255888e44171ffd48b591d19256884a969fe4da17caryclark            }
110355888e44171ffd48b591d19256884a969fe4da17caryclark        }
110455888e44171ffd48b591d19256884a969fe4da17caryclark        spanBase = test;
110555888e44171ffd48b591d19256884a969fe4da17caryclark    } while (!spanBase->final());
110655888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
110726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
110826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
110926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
11104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() {
11111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    this->init(this->fPts, this->fWeight, this->contour(), this->verb());
11124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
11134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
1114025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
1115025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const {
1116025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    if (fDebugBaseMax < 0 || fDebugBaseIndex == index) {
1117025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugBaseIndex = index;
1118025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugBaseMin = SkTMin(t, fDebugBaseMin);
1119025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugBaseMax = SkTMax(t, fDebugBaseMax);
1120025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        return;
1121025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    }
1122025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax);
1123025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    if (fDebugLastMax < 0 || fDebugLastIndex == index) {
1124025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugLastIndex = index;
1125025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugLastMin = SkTMin(t, fDebugLastMin);
1126025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        fDebugLastMax = SkTMax(t, fDebugLastMax);
1127025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        return;
1128025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    }
1129025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax);
1130025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0));
1131025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
1132025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
1133025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
113454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS
1135ff11428526843d3e03feb6843bd21f2d80536415Cary Clarkvoid SkOpSegment::debugShowActiveSpans(SkString* str) const {
11364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    debugValidate();
11374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (done()) {
11384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return;
11394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
11404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int lastId = -1;
11414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double lastT = -1;
114254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* span = &fHead;
114354359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
114454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->done()) {
11454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
11464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
11471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (lastId == this->debugID() && lastT == span->t()) {
11484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
11494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
11501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        lastId = this->debugID();
115154359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = span->t();
1152ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        str->appendf("%s id=%d", __FUNCTION__, this->debugID());
115355888e44171ffd48b591d19256884a969fe4da17caryclark        // since endpoints may have be adjusted, show actual computed curves
115455888e44171ffd48b591d19256884a969fe4da17caryclark        SkDCurve curvePart;
115555888e44171ffd48b591d19256884a969fe4da17caryclark        this->subDivide(span, span->next(), &curvePart);
115655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkDPoint* pts = curvePart.fCubic.fPts;
1157ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        str->appendf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY);
11584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
1159ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY);
11604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
11611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (SkPath::kConic_Verb == fVerb) {
1162ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" %1.9gf", curvePart.fConic.fWeight);
11631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
1164ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        str->appendf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t());
116554359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->windSum() == SK_MinS32) {
1166ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" windSum=?");
11674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
1168ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" windSum=%d", span->windSum());
1169624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1170624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() && span->oppSum() == SK_MinS32) {
1171ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" oppSum=?");
1172624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        } else if (span->oppValue() || span->oppSum() != SK_MinS32) {
1173ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" oppSum=%d", span->oppSum());
1174624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1175ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        str->appendf(" windValue=%d", span->windValue());
1176624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() || span->oppSum() != SK_MinS32) {
1177ff11428526843d3e03feb6843bd21f2d80536415Cary Clark            str->appendf(" oppValue=%d", span->oppValue());
11784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1179ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        str->appendf("\n");
118054359294a7c9dc54802d512a5d891a35c1663392caryclark   } while ((span = span->next()->upCastable()));
11814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
11824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
11834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
118454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE
118554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) {
118654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
11871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
11884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
11894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
11904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
11914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
119254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
119354359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t());
119454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
11954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
11964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
119754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
11984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
119954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windSum=");
120054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
120154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
120254359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
120354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
120454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
120554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d\n", span->windValue());
12064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
12074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
120854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding,
12094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                      int oppWinding) {
121054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
12111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
12124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
12134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
12144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
12154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
121654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
121754359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding);
121854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
121954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
122054359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
122154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
122254359294a7c9dc54802d512a5d891a35c1663392caryclark    }
122354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" newOppSum=");
122454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (oppWinding == SK_MinS32) {
122554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
122654359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
122754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", oppWinding);
122854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
122954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" oppSum=");
123054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->oppSum() == SK_MinS32) {
12314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
12324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
123354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->oppSum());
12344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
12354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" windSum=");
123654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
12374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
12384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
123954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
12404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
124154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue());
12424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
124354359294a7c9dc54802d512a5d891a35c1663392caryclark
12444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
12454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
124626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted
124726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted.
124826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark   This should be rarely called -- the test below is thorough and time consuming.
124955888e44171ffd48b591d19256884a969fe4da17caryclark   This checks the distance between start points; the distance between
125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/
125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const {
125326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpAngle* test = this;
125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* testSegment = test->segment();
125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testStartT = test->start()->t();
125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testStartPt = testSegment->dPtAtT(testStartT);
125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testEndT = test->end()->t();
125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testEndPt = testSegment->dPtAtT(testEndT);
126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testLenSq = testStartPt.distanceSquared(testEndPt);
126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID());
126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testMidT = (testStartT + testEndT) / 2;
126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* next = test;
126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((next = next->fNext) != this) {
126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkOpSegment* nextSegment = next->segment();
126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testMidDistSq = testSegment->distSq(testMidT, next);
126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testEndDistSq = testSegment->distSq(testEndT, next);
126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextStartT = next->start()->t();
126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT);
127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double distSq = testStartPt.distanceSquared(nextStartPt);
127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndT = next->end()->t();
127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidT = (nextStartT + nextEndT) / 2;
127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidDistSq = nextSegment->distSq(nextMidT, test);
127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndDistSq = nextSegment->distSq(nextEndT, test);
127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq,
127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    testSegment->debugID(), nextSegment->debugID());
127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq);
127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq);
127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq);
128026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq);
128126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT);
128226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextLenSq = nextStartPt.distanceSquared(nextEndPt);
128326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq);
128426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("\n");
128526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
128626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        test = test->fNext;
128755888e44171ffd48b591d19256884a969fe4da17caryclark    } while (test->fNext != this);
128826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
128926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
129026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
129154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE
129254359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const {
129354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkString result;
129454359294a7c9dc54802d512a5d891a35c1663392caryclark    switch (this->segment()->verb()) {
129554359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kLine_Verb:
1296eed356d281adbf93ecbd89cb23913a7861cd8578caryclark            result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fPart.fCurve),
129754359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
129854359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
129954359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kQuad_Verb:
1300eed356d281adbf93ecbd89cb23913a7861cd8578caryclark            result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fPart.fCurve),
130154359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
130254359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
13031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        case SkPath::kConic_Verb:
13041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            result.printf(CONIC_DEBUG_STR " id=%d",
1305eed356d281adbf93ecbd89cb23913a7861cd8578caryclark                    CONIC_DEBUG_DATA(fPart.fCurve, fPart.fCurve.fConic.fWeight),
13061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    this->segment()->debugID());
13071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            break;
130854359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kCubic_Verb:
1309eed356d281adbf93ecbd89cb23913a7861cd8578caryclark            result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fPart.fCurve),
131054359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
131154359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
131254359294a7c9dc54802d512a5d891a35c1663392caryclark        default:
131354359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(0);
13141b24933e52f50773de29332387a12721811f3012mtklein    }
131554359294a7c9dc54802d512a5d891a35c1663392caryclark    return result;
131654359294a7c9dc54802d512a5d891a35c1663392caryclark}
131754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
131854359294a7c9dc54802d512a5d891a35c1663392caryclark
1319624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
132054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const {
132154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
132254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
132354359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
132454359294a7c9dc54802d512a5d891a35c1663392caryclark        next->dumpOne(true);
132554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
132654359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
132754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
132854359294a7c9dc54802d512a5d891a35c1663392caryclark    next = first;
132954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
133054359294a7c9dc54802d512a5d891a35c1663392caryclark        next->debugValidate();
133154359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
133254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
1333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1334ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
1335ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
133654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const {
133755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
133855888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
133955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
134055888e44171ffd48b591d19256884a969fe4da17caryclark    }
134155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
134254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
134354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
134454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
134554359294a7c9dc54802d512a5d891a35c1663392caryclark    int wind = 0;
134654359294a7c9dc54802d512a5d891a35c1663392caryclark    int opp = 0;
134754359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastXor = -1;
134854359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastOppXor = -1;
134954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
135054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next->unorderable()) {
135154359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
135254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
135354359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpan* minSpan = next->start()->starter(next->end());
135454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (minSpan->windValue() == SK_MinS32) {
135554359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
135654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
135754359294a7c9dc54802d512a5d891a35c1663392caryclark        bool op = next->segment()->operand();
135854359294a7c9dc54802d512a5d891a35c1663392caryclark        bool isXor = next->segment()->isXor();
135954359294a7c9dc54802d512a5d891a35c1663392caryclark        bool oppXor = next->segment()->oppXor();
136054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM));
136154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM
136254359294a7c9dc54802d512a5d891a35c1663392caryclark                || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM));
136354359294a7c9dc54802d512a5d891a35c1663392caryclark        bool useXor = op ? oppXor : isXor;
136454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastXor == -1 || lastXor == (int) useXor);
136554359294a7c9dc54802d512a5d891a35c1663392caryclark        lastXor = (int) useXor;
1366624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue());
136754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
136854359294a7c9dc54802d512a5d891a35c1663392caryclark            wind &= 1;
136954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
137054359294a7c9dc54802d512a5d891a35c1663392caryclark        useXor = op ? isXor : oppXor;
137154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor);
137254359294a7c9dc54802d512a5d891a35c1663392caryclark        lastOppXor = (int) useXor;
1373624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue());
137454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
137554359294a7c9dc54802d512a5d891a35c1663392caryclark            opp &= 1;
137654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
137754359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
137854359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
137959d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark    SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail);
138059d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark    SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail);
138154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
138254359294a7c9dc54802d512a5d891a35c1663392caryclark}
138354359294a7c9dc54802d512a5d891a35c1663392caryclark
138454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const {
138554359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE
138654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
138754359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = first;
138854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkTDArray<const SkOpAngle*>(angles);
138954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
1390f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen//        SkASSERT_RELEASE(next->fSegment->debugContains(next));
139154359294a7c9dc54802d512a5d891a35c1663392caryclark        angles.push(next);
139254359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->next();
139354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next == first) {
139454359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
139554359294a7c9dc54802d512a5d891a35c1663392caryclark        }
1396f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen        SkASSERT_RELEASE(!angles.contains(next));
139754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!next) {
139854359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
139954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
140054359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (true);
140154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
140254359294a7c9dc54802d512a5d891a35c1663392caryclark}
140354359294a7c9dc54802d512a5d891a35c1663392caryclark
140455888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG
140555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over,
140655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpGlobalState* debugState) const {
140759d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark    SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail());
140859d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark    SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail());
140955888e44171ffd48b591d19256884a969fe4da17caryclark}
141055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
141126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
1412ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
1413ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// sets the span's end to the ptT referenced by the previous-next
1414ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log,
1415ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        const SkOpPtT* (SkCoincidentSpans::* getEnd)() const,
1416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) const ) const {
1417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpPtT* origPtT = (this->*getEnd)();
1418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSpanBase* origSpan = origPtT->span();
1419ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSpan* prev = origSpan->prev();
1420ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpPtT* testPtT = prev ? prev->next()->ptT()
1421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            : origSpan->upCast()->next()->prev()->ptT();
1422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (origPtT != testPtT) {
1423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        log->record(SkPathOpsDebug::kCorrectEnd_Glitch, this, origPtT, testPtT);
1424ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
1425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
1426ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
1427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
1428ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* Commented-out lines keep this in sync with correctEnds */
1429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// FIXME: member pointers have fallen out of favor and can be replaced with
1430ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// an alternative approach.
1431ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// makes all span ends agree with the segment's spans that define them
1432ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const {
1433ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTStart, nullptr);
1434ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTEnd, nullptr);
1435ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTStart, nullptr);
1436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTEnd, nullptr);
1437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
1438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
143955888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */
144030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// expand the range by checking adjacent spans for coincidence
1441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkCoincidentSpans::debugExpand(SkPathOpsDebug::GlitchLog* log) const {
144255888e44171ffd48b591d19256884a969fe4da17caryclark    bool expanded = false;
144355888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* segment = coinPtTStart()->segment();
144455888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* oppSegment = oppPtTStart()->segment();
144555888e44171ffd48b591d19256884a969fe4da17caryclark    do {
144655888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* start = coinPtTStart()->span()->upCast();
144755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* prev = start->prev();
144855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oppPtT;
144955888e44171ffd48b591d19256884a969fe4da17caryclark        if (!prev || !(oppPtT = prev->contains(oppSegment))) {
145055888e44171ffd48b591d19256884a969fe4da17caryclark            break;
145155888e44171ffd48b591d19256884a969fe4da17caryclark        }
145255888e44171ffd48b591d19256884a969fe4da17caryclark        double midT = (prev->t() + start->t()) / 2;
145355888e44171ffd48b591d19256884a969fe4da17caryclark        if (!segment->isClose(midT, oppSegment)) {
145455888e44171ffd48b591d19256884a969fe4da17caryclark            break;
145555888e44171ffd48b591d19256884a969fe4da17caryclark        }
1456ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, prev->ptT(), oppPtT);
145755888e44171ffd48b591d19256884a969fe4da17caryclark        expanded = true;
145855888e44171ffd48b591d19256884a969fe4da17caryclark    } while (false);  // actual continues while expansion is possible
145955888e44171ffd48b591d19256884a969fe4da17caryclark    do {
146055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coinPtTEnd()->span();
146155888e44171ffd48b591d19256884a969fe4da17caryclark        SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next();
146230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        if (next && next->deleted()) {
146330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            break;
146430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        }
146555888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oppPtT;
146655888e44171ffd48b591d19256884a969fe4da17caryclark        if (!next || !(oppPtT = next->contains(oppSegment))) {
146755888e44171ffd48b591d19256884a969fe4da17caryclark            break;
146855888e44171ffd48b591d19256884a969fe4da17caryclark        }
146955888e44171ffd48b591d19256884a969fe4da17caryclark        double midT = (end->t() + next->t()) / 2;
147055888e44171ffd48b591d19256884a969fe4da17caryclark        if (!segment->isClose(midT, oppSegment)) {
147155888e44171ffd48b591d19256884a969fe4da17caryclark            break;
147255888e44171ffd48b591d19256884a969fe4da17caryclark        }
1473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, next->ptT(), oppPtT);
147455888e44171ffd48b591d19256884a969fe4da17caryclark        expanded = true;
147555888e44171ffd48b591d19256884a969fe4da17caryclark    } while (false);  // actual continues while expansion is possible
147655888e44171ffd48b591d19256884a969fe4da17caryclark    return expanded;
147755888e44171ffd48b591d19256884a969fe4da17caryclark}
147855888e44171ffd48b591d19256884a969fe4da17caryclark
1479ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below
1480ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* base, const SkOpSpanBase* testSpan) const {
1481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpPtT* testPtT = testSpan->ptT();
1482ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpPtT* stopPtT = testPtT;
1483ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSegment* baseSeg = base->segment();
1484ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    while ((testPtT = testPtT->next()) != stopPtT) {
1485ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        const SkOpSegment* testSeg = testPtT->segment();
1486ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (testPtT->deleted()) {
1487ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            continue;
1488ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1489ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (testSeg == baseSeg) {
1490ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            continue;
1491ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1492ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (testPtT->span()->ptT() != testPtT) {
1493ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            continue;
1494ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1495ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (this->contains(baseSeg, testSeg, testPtT->fT)) {
1496ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            continue;
1497ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1498ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        // intersect perp with base->ptT() with testPtT->segment()
1499ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkDVector dxdy = baseSeg->dSlopeAtT(base->t());
1500ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        const SkPoint& pt = base->pt();
1501ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}};
1502ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkIntersections i;
1503ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i);
1504ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        for (int index = 0; index < i.used(); ++index) {
1505ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            double t = i[0][index];
1506ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (!between(0, t, 1)) {
1507ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                continue;
1508ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1509ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkDPoint oppPt = i.pt(index);
1510ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (!oppPt.approximatelyEqual(pt)) {
1511ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                continue;
1512ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1513ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg);
1514ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkOpPtT* oppStart = writableSeg->addT(t);
1515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (oppStart == testPtT) {
1516ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                continue;
1517ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1518ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkOpSpan* writableBase = const_cast<SkOpSpan*>(base);
1519ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            oppStart->span()->addOpp(writableBase);
1520ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (oppStart->deleted()) {
1521ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                continue;
1522ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1523ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkOpSegment* coinSeg = base->segment();
1524ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            SkOpSegment* oppSeg = oppStart->segment();
1525ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            double coinTs, coinTe, oppTs, oppTe;
1526ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (Ordered(coinSeg, oppSeg)) {
1527ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                coinTs = base->t();
1528ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                coinTe = testSpan->t();
1529ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oppTs = oppStart->fT;
1530ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oppTe = testPtT->fT;
1531ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            } else {
1532ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                SkTSwap(coinSeg, oppSeg);
1533ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                coinTs = oppStart->fT;
1534ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                coinTe = testPtT->fT;
1535ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oppTs = base->t();
1536ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oppTe = testSpan->t();
1537ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1538ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (coinTs > coinTe) {
1539ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                SkTSwap(coinTs, coinTe);
1540ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                SkTSwap(oppTs, oppTe);
1541ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1542ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            bool added;
1543ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added), false) {
1544ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                return;
1545ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1546ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1547ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
1548ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
1549ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
1550ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
1551ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below
1552ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* ptT) const {
1553ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    FAIL_IF(!ptT->span()->upCastable(), ptT->span());
1554ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSpan* base = ptT->span()->upCast();
1555ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSpan* prev = base->prev();
1556ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    FAIL_IF(!prev, ptT->span());
1557ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!prev->isCanceled()) {
1558ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (this->debugAddEndMovedSpans(log, base, base->prev()), false) {
1559ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
1560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
1562ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!base->isCanceled()) {
1563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (this->debugAddEndMovedSpans(log, base, base->next()), false) {
1564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
1565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
1567ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
1568ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
1569ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
1570ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/*  If A is coincident with B and B includes an endpoint, and A's matching point
1571ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    is not the endpoint (i.e., there's an implied line connecting B-end and A)
1572ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    then assume that the same implied line may intersect another curve close to B.
1573ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    Since we only care about coincidence that was undetected, look at the
1574ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but
1575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    next door) and see if the A matching point is close enough to form another
1576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    coincident pair. If so, check for a new coincident span between B-end/A ptT loop
1577ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    and the adjacent ptT loop.
1578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark*/
1579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const {
1580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkCoincidentSpans* span = fHead;
1581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!span) {
1582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        return;
1583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
1584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark//    fTop = span;
1585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark//    fHead = nullptr;
1586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
1587ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) {
1588ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            FAIL_IF(1 == span->coinPtTStart()->fT, span);
1589ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            bool onEnd = span->coinPtTStart()->fT == 0;
1590ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            bool oOnEnd = zero_or_one(span->oppPtTStart()->fT);
1591ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (onEnd) {
1592ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (!oOnEnd) {  // if both are on end, any nearby intersect was already found
1593ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    if (this->debugAddEndMovedSpans(log, span->oppPtTStart()), false) {
1594ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        return;
1595ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    }
1596ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
1597ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            } else if (oOnEnd) {
1598ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (this->debugAddEndMovedSpans(log, span->coinPtTStart()), false) {
1599ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    return;
1600ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
1601ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1602ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1603ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) {
1604ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            bool onEnd = span->coinPtTEnd()->fT == 1;
1605ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT);
1606ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (onEnd) {
1607ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (!oOnEnd) {
1608ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    if (this->debugAddEndMovedSpans(log, span->oppPtTEnd()), false) {
1609ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        return;
1610ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    }
1611ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
1612ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            } else if (oOnEnd) {
1613ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (this->debugAddEndMovedSpans(log, span->coinPtTEnd()), false) {
1614ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    return;
1615ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
1616ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
1617ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
1618ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((span = span->next()));
1619ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark//    this->restoreHead();
1620ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
1621ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
1622ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
162355888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */
162455888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans
162555888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span
1626ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddExpanded(SkPathOpsDebug::GlitchLog* log) const {
1627a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark//    DEBUG_SET_PHASE();
162826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = this->fHead;
162926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
1630ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark        return;
1631ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    }
163226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
163355888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* startPtT = coin->coinPtTStart();
163455888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* oStartPtT = coin->oppPtTStart();
1635ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        double priorT = startPtT->fT;
1636ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        double oPriorT = oStartPtT->fT;
1637ff11428526843d3e03feb6843bd21f2d80536415Cary Clark        FAIL_IF(!startPtT->contains(oStartPtT), coin);
1638ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd()));
163926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* start = startPtT->span();
164026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oStart = oStartPtT->span();
164155888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coin->coinPtTEnd()->span();
164255888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span();
164330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        FAIL_IF(oEnd->deleted(), coin);
164430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        FAIL_IF(!start->upCastable(), coin);
164526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* test = start->upCast()->next();
1646ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        FAIL_IF(!coin->flipped() && !oStart->upCastable(), coin);
164755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next();
1648ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        FAIL_IF(!oTest, coin);
1649ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        const SkOpSegment* seg = start->segment();
1650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        const SkOpSegment* oSeg = oStart->segment();
165126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while (test != end || oTest != oEnd) {
1652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            const SkOpPtT* containedOpp = test->ptT()->contains(oSeg);
1653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            const SkOpPtT* containedThis = oTest->ptT()->contains(seg);
1654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (!containedOpp || !containedThis) {
1655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                // choose the ends, or the first common pt-t list shared by both
1656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                double nextT, oNextT;
1657ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (containedOpp) {
1658ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    nextT = test->t();
1659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    oNextT = containedOpp->fT;
1660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                } else if (containedThis) {
1661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    nextT = containedThis->fT;
1662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    oNextT = oTest->t();
1663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                } else {
1664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    // iterate through until a pt-t list found that contains the other
1665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    const SkOpSpanBase* walk = test;
1666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    const SkOpPtT* walkOpp;
1667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    do {
1668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        FAIL_IF(!walk->upCastable(), coin);
1669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        walk = walk->upCast()->next();
1670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    } while (!(walkOpp = walk->ptT()->contains(oSeg))
1671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                            && walk != coin->coinPtTEnd()->span());
1672a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark                    FAIL_IF(!walkOpp, coin);
1673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    nextT = walk->t();
1674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    oNextT = walkOpp->fT;
1675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
167626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // use t ranges to guess which one is missing
1677a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark                double startRange = nextT - priorT;
167830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                FAIL_IF(!startRange, coin);
1679a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark                double startPart = (test->t() - priorT) / startRange;
1680a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark                double oStartRange = oNextT - oPriorT;
168130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                FAIL_IF(!oStartRange, coin);
168226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
168330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                FAIL_IF(startPart == oStartPart, coin);
1684ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart
1685ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        : !!containedThis;
168655888e44171ffd48b591d19256884a969fe4da17caryclark                bool startOver = false;
1687ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                addToOpp ? log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch,
1688ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        oPriorT + oStartRange * startPart, test)
1689ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        : log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch,
1690ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        priorT + startRange * oStartPart, oTest);
1691ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark         //       FAIL_IF(!success, coin);
169255888e44171ffd48b591d19256884a969fe4da17caryclark                if (startOver) {
169355888e44171ffd48b591d19256884a969fe4da17caryclark                    test = start;
169455888e44171ffd48b591d19256884a969fe4da17caryclark                    oTest = oStart;
169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
1696ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                end = coin->coinPtTEnd()->span();
1697ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oEnd = coin->oppPtTEnd()->span();
169826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
169955888e44171ffd48b591d19256884a969fe4da17caryclark            if (test != end) {
1700ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                FAIL_IF(!test->upCastable(), coin);
1701ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                priorT = test->t();
170226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                test = test->upCast()->next();
170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
170455888e44171ffd48b591d19256884a969fe4da17caryclark            if (oTest != oEnd) {
1705ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                oPriorT = oTest->t();
170655888e44171ffd48b591d19256884a969fe4da17caryclark                oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next();
1707ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                FAIL_IF(!oTest, coin);
170826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
170926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
171055888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
171155888e44171ffd48b591d19256884a969fe4da17caryclark    return;
171255888e44171ffd48b591d19256884a969fe4da17caryclark}
171355888e44171ffd48b591d19256884a969fe4da17caryclark
171455888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */
17158016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// note that over1s, over1e, over2s, over2e are ordered
1716ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddIfMissing(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s,
171781a478ca6c36aac3e53ce0373a281ac8940f4780caryclark        double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added,
17188016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        const SkOpPtT* over1e, const SkOpPtT* over2e) const {
17198016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(tStart < tEnd);
17208016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over1s->fT < over1e->fT);
17218016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(between(over1s->fT, tStart, over1e->fT));
17228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(between(over1s->fT, tEnd, over1e->fT));
17238016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over2s->fT < over2e->fT);
17248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(between(over2s->fT, tStart, over2e->fT));
17258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(between(over2s->fT, tEnd, over2e->fT));
17268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over1s->segment() == over1e->segment());
17278016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over2s->segment() == over2e->segment());
17288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over1s->segment() == over2s->segment());
17298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over1s->segment() != coinSeg);
17308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(over1s->segment() != oppSeg);
17318016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    SkASSERT(coinSeg != oppSeg);
173226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double coinTs, coinTe, oppTs, oppTe;
17338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    coinTs = TRange(over1s, tStart, coinSeg  SkDEBUGPARAMS(over1e));
17348016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    coinTe = TRange(over1s, tEnd, coinSeg  SkDEBUGPARAMS(over1e));
17358016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    if (coinSeg->collapsed(coinTs, coinTe)) {
1736ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, coinSeg);
173726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
17388016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    oppTs = TRange(over2s, tStart, oppSeg  SkDEBUGPARAMS(over2e));
17398016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    oppTe = TRange(over2s, tEnd, oppSeg  SkDEBUGPARAMS(over2e));
17408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    if (oppSeg->collapsed(oppTs, oppTe)) {
1741ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, oppSeg);
174226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
17438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    if (coinTs > coinTe) {
17448016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        SkTSwap(coinTs, coinTe);
174526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(oppTs, oppTe);
174626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
1747ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added
17488016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            );
174955888e44171ffd48b591d19256884a969fe4da17caryclark}
175055888e44171ffd48b591d19256884a969fe4da17caryclark
175155888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */
175230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by addEndMovedSpans(), a returned false propogates out to an abort.
175330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by AddIfMissing(), a returned false indicates there was nothing to add
1754ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log,
175530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
175681a478ca6c36aac3e53ce0373a281ac8940f4780caryclark        double coinTs, double coinTe, double oppTs, double oppTe, bool* added) const {
175755888e44171ffd48b591d19256884a969fe4da17caryclark    SkTDArray<SkCoincidentSpans*> overlaps;
1758ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkOPASSERT(!fTop);   // this is (correctly) reversed in addifMissing()
175981a478ca6c36aac3e53ce0373a281ac8940f4780caryclark    if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe,
176081a478ca6c36aac3e53ce0373a281ac8940f4780caryclark            &overlaps)) {
176155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
176255888e44171ffd48b591d19256884a969fe4da17caryclark    }
176355888e44171ffd48b591d19256884a969fe4da17caryclark    if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs,
176455888e44171ffd48b591d19256884a969fe4da17caryclark            coinTe, oppTs, oppTe, &overlaps)) {
176555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
176655888e44171ffd48b591d19256884a969fe4da17caryclark    }
176755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr;
176855888e44171ffd48b591d19256884a969fe4da17caryclark    for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing
176955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkCoincidentSpans* test = overlaps[index];
177055888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) {
1771ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTStart());
177255888e44171ffd48b591d19256884a969fe4da17caryclark        }
177355888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) {
1774ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTEnd());
177555888e44171ffd48b591d19256884a969fe4da17caryclark        }
177655888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->flipped()
177755888e44171ffd48b591d19256884a969fe4da17caryclark                ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT
177855888e44171ffd48b591d19256884a969fe4da17caryclark                : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) {
1779ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTStart());
178055888e44171ffd48b591d19256884a969fe4da17caryclark        }
178155888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->flipped()
178255888e44171ffd48b591d19256884a969fe4da17caryclark                ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT
178355888e44171ffd48b591d19256884a969fe4da17caryclark                : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) {
1784ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTEnd());
178555888e44171ffd48b591d19256884a969fe4da17caryclark        }
1786ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (!fHead) { this->debugRelease(log, fHead, test);
1787ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            this->debugRelease(log, fTop, test);
178855888e44171ffd48b591d19256884a969fe4da17caryclark        }
178955888e44171ffd48b591d19256884a969fe4da17caryclark    }
179055888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg);
179155888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg);
179230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg);
179330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(cs != ce || !cs, coinSeg);
179455888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg);
179555888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg);
179630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg);
179755888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !cs || !cs->deleted());
179855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !os || !os->deleted());
179955888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !ce || !ce->deleted());
180055888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(true || !oe || !oe->deleted());
180155888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr;
180255888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr;
180330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg);
180430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(csExisting && (csExisting == ce ||
180530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg);
180630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(ceExisting && (ceExisting == cs ||
180730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            ceExisting->contains(csExisting ? csExisting : cs)), coinSeg);
180855888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr;
180955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr;
181030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg);
181130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(osExisting && (osExisting == oe ||
181230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg);
181330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(oeExisting && (oeExisting == os ||
181430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            oeExisting->contains(osExisting ? osExisting : os)), oppSeg);
181555888e44171ffd48b591d19256884a969fe4da17caryclark    bool csDeleted = false, osDeleted = false, ceDeleted = false,  oeDeleted = false;
181655888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
181755888e44171ffd48b591d19256884a969fe4da17caryclark    if (!cs || !os) {
181855888e44171ffd48b591d19256884a969fe4da17caryclark        if (!cs)
1819ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            cs = coinSeg->debugAddT(coinTs, log);
182055888e44171ffd48b591d19256884a969fe4da17caryclark        if (!os)
1821ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            os = oppSeg->debugAddT(oppTs, log);
182230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//      RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable);
1823ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (cs && os) cs->span()->debugAddOpp(log, os->span());
182455888e44171ffd48b591d19256884a969fe4da17caryclark//         cs = csWritable;
182530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//         os = osWritable->active();
182630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg);
182755888e44171ffd48b591d19256884a969fe4da17caryclark    }
182855888e44171ffd48b591d19256884a969fe4da17caryclark    if (!ce || !oe) {
182955888e44171ffd48b591d19256884a969fe4da17caryclark        if (!ce)
1830ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            ce = coinSeg->debugAddT(coinTe, log);
183155888e44171ffd48b591d19256884a969fe4da17caryclark        if (!oe)
1832ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            oe = oppSeg->debugAddT(oppTe, log);
1833ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (ce && oe) ce->span()->debugAddOpp(log, oe->span());
183455888e44171ffd48b591d19256884a969fe4da17caryclark//         ce = ceWritable;
183555888e44171ffd48b591d19256884a969fe4da17caryclark//         oe = oeWritable;
183655888e44171ffd48b591d19256884a969fe4da17caryclark    }
183755888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
183830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(csDeleted, coinSeg);
183930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(osDeleted, oppSeg);
184030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(ceDeleted, coinSeg);
184130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    RETURN_FALSE_IF(oeDeleted, oppSeg);
18428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg);
18438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    bool result = true;
184455888e44171ffd48b591d19256884a969fe4da17caryclark    if (overlap) {
184555888e44171ffd48b591d19256884a969fe4da17caryclark        if (overlap->coinPtTStart()->segment() == coinSeg) {
1846ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
184755888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
184855888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppTs > oppTe) {
184955888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(coinTs, coinTe);
185055888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(oppTs, oppTe);
185155888e44171ffd48b591d19256884a969fe4da17caryclark            }
1852ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe);
185355888e44171ffd48b591d19256884a969fe4da17caryclark        }
18548016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE
18558016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        if (result) {
18568016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark             overlap->debugShow();
18578016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        }
185855888e44171ffd48b591d19256884a969fe4da17caryclark#endif
185955888e44171ffd48b591d19256884a969fe4da17caryclark    } else {
1860ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        log->record(SkPathOpsDebug::kAddMissingCoin_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
18618016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE
18628016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        fHead->debugShow();
186355888e44171ffd48b591d19256884a969fe4da17caryclark#endif
186455888e44171ffd48b591d19256884a969fe4da17caryclark    }
186555888e44171ffd48b591d19256884a969fe4da17caryclark    this->debugValidate();
18668016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    return (void) result;
186726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
186826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
186955888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing()
187055888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */
187155888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */
187255888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again
1873ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddMissing(SkPathOpsDebug::GlitchLog* log, bool* added) const {
187426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* outer = fHead;
1875ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    *added = false;
187626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!outer) {
187726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
187826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
187955888e44171ffd48b591d19256884a969fe4da17caryclark    // fTop = outer;
188055888e44171ffd48b591d19256884a969fe4da17caryclark    // fHead = nullptr;
188126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
188226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing can modify the list that this is walking
188326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // save head so that walker can iterate over old data unperturbed
188426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing adds to head freely then add saved head in the end
18858016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        const SkOpPtT* ocs = outer->coinPtTStart();
18868016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        SkASSERT(!ocs->deleted());
18878016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        const SkOpSegment* outerCoin = ocs->segment();
18888016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        SkASSERT(!outerCoin->done());  // if it's done, should have already been removed from list
18898016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        const SkOpPtT* oos = outer->oppPtTStart();
1890ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (oos->deleted()) {
1891ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
1892ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
18938016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        const SkOpSegment* outerOpp = oos->segment();
18948016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark        SkASSERT(!outerOpp->done());
18958016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark//        SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin);
18968016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark//        SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp);
189726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkCoincidentSpans* inner = outer;
189855888e44171ffd48b591d19256884a969fe4da17caryclark        while ((inner = inner->next())) {
189955888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
190026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double overS, overE;
19018016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            const SkOpPtT* ics = inner->coinPtTStart();
19028016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkASSERT(!ics->deleted());
19038016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            const SkOpSegment* innerCoin = ics->segment();
19048016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkASSERT(!innerCoin->done());
19058016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            const SkOpPtT* ios = inner->oppPtTStart();
19068016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkASSERT(!ios->deleted());
19078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            const SkOpSegment* innerOpp = ios->segment();
19088016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark            SkASSERT(!innerOpp->done());
19098016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark//            SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin);
19108016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark//            SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp);
191155888e44171ffd48b591d19256884a969fe4da17caryclark            if (outerCoin == innerCoin) {
19128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* oce = outer->coinPtTEnd();
1913ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (oce->deleted()) {
1914ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    return;
1915ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
19168016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ice = inner->coinPtTEnd();
19178016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!ice->deleted());
19188016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) {
1919ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    this->debugAddIfMissing(log, ocs->starter(oce), ics->starter(ice),
192081a478ca6c36aac3e53ce0373a281ac8940f4780caryclark                            overS, overE, outerOpp, innerOpp, added,
19218016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ocs->debugEnder(oce),
19228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ics->debugEnder(ice));
192326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
192455888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerCoin == innerOpp) {
19258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* oce = outer->coinPtTEnd();
19268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!oce->deleted());
19278016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ioe = inner->oppPtTEnd();
19288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!ioe->deleted());
19298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) {
1930ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    this->debugAddIfMissing(log, ocs->starter(oce), ios->starter(ioe),
193181a478ca6c36aac3e53ce0373a281ac8940f4780caryclark                            overS, overE, outerOpp, innerCoin, added,
19328016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ocs->debugEnder(oce),
19338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ios->debugEnder(ioe));
193426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
193555888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerOpp == innerCoin) {
19368016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ooe = outer->oppPtTEnd();
19378016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!ooe->deleted());
19388016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ice = inner->coinPtTEnd();
19398016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!ice->deleted());
194055888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(outerCoin != innerOpp);
19418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) {
1942ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    this->debugAddIfMissing(log, oos->starter(ooe), ics->starter(ice),
194381a478ca6c36aac3e53ce0373a281ac8940f4780caryclark                            overS, overE, outerCoin, innerOpp, added,
19448016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            oos->debugEnder(ooe),
19458016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ics->debugEnder(ice));
194626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
194755888e44171ffd48b591d19256884a969fe4da17caryclark            } else if (outerOpp == innerOpp) {
19488016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ooe = outer->oppPtTEnd();
19498016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                SkASSERT(!ooe->deleted());
19508016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                const SkOpPtT* ioe = inner->oppPtTEnd();
1951ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                if (ioe->deleted()) {
1952ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    return;
1953ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                }
195455888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(outerCoin != innerCoin);
19558016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) {
1956ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    this->debugAddIfMissing(log, oos->starter(ooe), ios->starter(ioe),
195781a478ca6c36aac3e53ce0373a281ac8940f4780caryclark                            overS, overE, outerCoin, innerCoin, added,
19588016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            oos->debugEnder(ooe),
19598016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark                            ios->debugEnder(ioe));
196026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
196126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
196255888e44171ffd48b591d19256884a969fe4da17caryclark            this->debugValidate();
196355888e44171ffd48b591d19256884a969fe4da17caryclark        }
196455888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((outer = outer->next()));
196555888e44171ffd48b591d19256884a969fe4da17caryclark    // this->restoreHead();
196655888e44171ffd48b591d19256884a969fe4da17caryclark    return;
196755888e44171ffd48b591d19256884a969fe4da17caryclark}
196855888e44171ffd48b591d19256884a969fe4da17caryclark
196955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release()
1970ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const {
197130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkCoincidentSpans* head = coin;
197230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkCoincidentSpans* prev = nullptr;
197330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkCoincidentSpans* next;
197430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    do {
197530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        next = coin->next();
197630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        if (coin == remove) {
197730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            if (prev) {
197830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                prev->setNext(next);
197930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            } else if (head == fHead) {
198030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                fHead = next;
198130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            } else {
198230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                fTop = next;
198330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            }
1984ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin);
198530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        }
198630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        prev = coin;
198730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    } while ((coin = next));
198830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    return;
198930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark}
199030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
1991ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const {
199255888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* coin = fHead;
199355888e44171ffd48b591d19256884a969fe4da17caryclark    if (!coin) {
199455888e44171ffd48b591d19256884a969fe4da17caryclark        return;
199555888e44171ffd48b591d19256884a969fe4da17caryclark    }
199655888e44171ffd48b591d19256884a969fe4da17caryclark    do {
199755888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->coinPtTStart()->segment() == deleted
199855888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->coinPtTEnd()->segment() == deleted
199955888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->oppPtTStart()->segment() == deleted
200055888e44171ffd48b591d19256884a969fe4da17caryclark                || coin->oppPtTEnd()->segment() == deleted) {
2001ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin);
200230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        }
200355888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
200426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
200526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
200655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand()
200755888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence
2008ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkOpCoincidence::debugExpand(SkPathOpsDebug::GlitchLog* log) const {
200926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
201026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
201126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return false;
201226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
201326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    bool expanded = false;
201426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
2015ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (coin->debugExpand(log)) {
201655888e44171ffd48b591d19256884a969fe4da17caryclark            // check to see if multiple spans expanded so they are now identical
201755888e44171ffd48b591d19256884a969fe4da17caryclark            const SkCoincidentSpans* test = fHead;
201855888e44171ffd48b591d19256884a969fe4da17caryclark            do {
201955888e44171ffd48b591d19256884a969fe4da17caryclark                if (coin == test) {
202055888e44171ffd48b591d19256884a969fe4da17caryclark                    continue;
202155888e44171ffd48b591d19256884a969fe4da17caryclark                }
202255888e44171ffd48b591d19256884a969fe4da17caryclark                if (coin->coinPtTStart() == test->coinPtTStart()
202355888e44171ffd48b591d19256884a969fe4da17caryclark                        && coin->oppPtTStart() == test->oppPtTStart()) {
2024ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, fHead, test->coinPtTStart());
202555888e44171ffd48b591d19256884a969fe4da17caryclark                    break;
202655888e44171ffd48b591d19256884a969fe4da17caryclark                }
202755888e44171ffd48b591d19256884a969fe4da17caryclark            } while ((test = test->next()));
202855888e44171ffd48b591d19256884a969fe4da17caryclark            expanded = true;
202926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
203055888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
203126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return expanded;
203226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
203326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
203455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark()
203555888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */
2036ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMark(SkPathOpsDebug::GlitchLog* log) const {
203726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
203826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
203926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
204026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
204126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
2042ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable(), coin);
204355888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast();
204455888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(start->deleted());
204555888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* end = coin->coinPtTEndWritable()->span();
204655888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(end->deleted());
204755888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span();
204855888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(oStart->deleted());
204955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span();
205055888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(oEnd->deleted());
205155888e44171ffd48b591d19256884a969fe4da17caryclark        bool flipped = coin->flipped();
205226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (flipped) {
205326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkTSwap(oStart, oEnd);
205426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
205555888e44171ffd48b591d19256884a969fe4da17caryclark        /* coin and opp spans may not match up. Mark the ends, and then let the interior
205655888e44171ffd48b591d19256884a969fe4da17caryclark           get marked as many times as the spans allow */
2057ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        start->debugInsertCoincidence(log, oStart->upCast());
2058ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        end->debugInsertCoinEnd(log, oEnd);
205955888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* segment = start->segment();
206055888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpSegment* oSegment = oStart->segment();
206126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* next = start;
206226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oNext = oStart;
2063a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        bool ordered;
2064a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark        FAIL_IF(!coin->ordered(&ordered), coin);
206555888e44171ffd48b591d19256884a969fe4da17caryclark        while ((next = next->upCast()->next()) != end) {
2066ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            FAIL_IF(!next->upCastable(), coin);
2067ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (next->upCast()->debugInsertCoincidence(log, oSegment, flipped, ordered), false) {
206855888e44171ffd48b591d19256884a969fe4da17caryclark                return;
206926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
207055888e44171ffd48b591d19256884a969fe4da17caryclark        }
207155888e44171ffd48b591d19256884a969fe4da17caryclark        while ((oNext = oNext->upCast()->next()) != oEnd) {
2072ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            FAIL_IF(!oNext->upCastable(), coin);
2073ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (oNext->upCast()->debugInsertCoincidence(log, segment, flipped, ordered), false) {
207455888e44171ffd48b591d19256884a969fe4da17caryclark                return;
207526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
207655888e44171ffd48b591d19256884a969fe4da17caryclark        }
207755888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((coin = coin->next()));
207855888e44171ffd48b591d19256884a969fe4da17caryclark    return;
207955888e44171ffd48b591d19256884a969fe4da17caryclark}
208055888e44171ffd48b591d19256884a969fe4da17caryclark#endif
208155888e44171ffd48b591d19256884a969fe4da17caryclark
2082ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
208355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed()
2084ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const {
208530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkCoincidentSpans* head = coin;
208655888e44171ffd48b591d19256884a969fe4da17caryclark    while (coin) {
208755888e44171ffd48b591d19256884a969fe4da17caryclark        if (coin->collapsed(test)) {
208855888e44171ffd48b591d19256884a969fe4da17caryclark            if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) {
2089ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin);
209026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
209155888e44171ffd48b591d19256884a969fe4da17caryclark            if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) {
2092ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin);
209355888e44171ffd48b591d19256884a969fe4da17caryclark            }
2094ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            this->debugRelease(log, head, coin);
209555888e44171ffd48b591d19256884a969fe4da17caryclark        }
209655888e44171ffd48b591d19256884a969fe4da17caryclark        coin = coin->next();
209755888e44171ffd48b591d19256884a969fe4da17caryclark    }
209855888e44171ffd48b591d19256884a969fe4da17caryclark}
209955888e44171ffd48b591d19256884a969fe4da17caryclark
210055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed()
2101ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const {
2102ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugMarkCollapsed(log, fHead, test);
2103ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugMarkCollapsed(log, fTop, test);
210426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
210526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
210626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
210755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const {
21086c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(),
210955888e44171ffd48b591d19256884a969fe4da17caryclark            coinPtTStart()->fT, coinPtTEnd()->fT);
21106c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(),
211155888e44171ffd48b591d19256884a969fe4da17caryclark            oppPtTStart()->fT, oppPtTEnd()->fT);
211255888e44171ffd48b591d19256884a969fe4da17caryclark}
211355888e44171ffd48b591d19256884a969fe4da17caryclark
2114624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const {
211555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
211655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* span = fHead;
2117624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    while (span) {
211855888e44171ffd48b591d19256884a969fe4da17caryclark        span->debugShow();
211955888e44171ffd48b591d19256884a969fe4da17caryclark        span = span->next();
2120624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
212155888e44171ffd48b591d19256884a969fe4da17caryclark#endif
2122624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
2123624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
2124ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
21256c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end,
212655888e44171ffd48b591d19256884a969fe4da17caryclark        double oStart, double oEnd, const SkOpSegment* oSegment,
2127ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkPathOpsDebug::GlitchLog* log) {
212855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(next != end);
212955888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(!next->contains(end) || log);
213055888e44171ffd48b591d19256884a969fe4da17caryclark    if (next->t() > end->t()) {
213155888e44171ffd48b591d19256884a969fe4da17caryclark        SkTSwap(next, end);
213255888e44171ffd48b591d19256884a969fe4da17caryclark    }
213355888e44171ffd48b591d19256884a969fe4da17caryclark    do {
213455888e44171ffd48b591d19256884a969fe4da17caryclark        const SkOpPtT* ptT = next->ptT();
213555888e44171ffd48b591d19256884a969fe4da17caryclark        int index = 0;
213627c015dfcf4e2b8fb1abe327cc40204e2a4f452acaryclark        bool somethingBetween = false;
213755888e44171ffd48b591d19256884a969fe4da17caryclark        do {
213855888e44171ffd48b591d19256884a969fe4da17caryclark            ++index;
213955888e44171ffd48b591d19256884a969fe4da17caryclark            ptT = ptT->next();
214055888e44171ffd48b591d19256884a969fe4da17caryclark            const SkOpPtT* checkPtT = next->ptT();
214155888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT == checkPtT) {
214255888e44171ffd48b591d19256884a969fe4da17caryclark                break;
214355888e44171ffd48b591d19256884a969fe4da17caryclark            }
214455888e44171ffd48b591d19256884a969fe4da17caryclark            bool looped = false;
214555888e44171ffd48b591d19256884a969fe4da17caryclark            for (int check = 0; check < index; ++check) {
214655888e44171ffd48b591d19256884a969fe4da17caryclark                if ((looped = checkPtT == ptT)) {
214755888e44171ffd48b591d19256884a969fe4da17caryclark                    break;
214855888e44171ffd48b591d19256884a969fe4da17caryclark                }
214955888e44171ffd48b591d19256884a969fe4da17caryclark                checkPtT = checkPtT->next();
215055888e44171ffd48b591d19256884a969fe4da17caryclark            }
215155888e44171ffd48b591d19256884a969fe4da17caryclark            if (looped) {
215255888e44171ffd48b591d19256884a969fe4da17caryclark                SkASSERT(0);
215355888e44171ffd48b591d19256884a969fe4da17caryclark                break;
215455888e44171ffd48b591d19256884a969fe4da17caryclark            }
215555888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->deleted()) {
215655888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
215755888e44171ffd48b591d19256884a969fe4da17caryclark            }
215855888e44171ffd48b591d19256884a969fe4da17caryclark            if (ptT->segment() != oSegment) {
215955888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
216055888e44171ffd48b591d19256884a969fe4da17caryclark            }
216155888e44171ffd48b591d19256884a969fe4da17caryclark            somethingBetween |= between(oStart, ptT->fT, oEnd);
216255888e44171ffd48b591d19256884a969fe4da17caryclark        } while (true);
216355888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(somethingBetween);
216455888e44171ffd48b591d19256884a969fe4da17caryclark    } while (next != end && (next = next->upCast()->next()));
216555888e44171ffd48b591d19256884a969fe4da17caryclark}
216655888e44171ffd48b591d19256884a969fe4da17caryclark
216755888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list,
2168ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkPathOpsDebug::GlitchLog* log) {
216955888e44171ffd48b591d19256884a969fe4da17caryclark    if (!list) {
217055888e44171ffd48b591d19256884a969fe4da17caryclark        return;
217155888e44171ffd48b591d19256884a969fe4da17caryclark    }
217255888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* coinSeg = test->coinPtTStart()->segment();
217355888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(coinSeg == test->coinPtTEnd()->segment());
217455888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpSegment* oppSeg = test->oppPtTStart()->segment();
217555888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(oppSeg == test->oppPtTEnd()->segment());
217655888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(coinSeg != test->oppPtTStart()->segment());
217755888e44171ffd48b591d19256884a969fe4da17caryclark    SkDEBUGCODE(double tcs = test->coinPtTStart()->fT);
217855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tcs, 1));
217955888e44171ffd48b591d19256884a969fe4da17caryclark    SkDEBUGCODE(double tce = test->coinPtTEnd()->fT);
218055888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tce, 1));
218155888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(tcs < tce);
218255888e44171ffd48b591d19256884a969fe4da17caryclark    double tos = test->oppPtTStart()->fT;
218355888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, tos, 1));
218455888e44171ffd48b591d19256884a969fe4da17caryclark    double toe = test->oppPtTEnd()->fT;
218555888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(between(0, toe, 1));
218655888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(tos != toe);
218755888e44171ffd48b591d19256884a969fe4da17caryclark    if (tos > toe) {
218855888e44171ffd48b591d19256884a969fe4da17caryclark        SkTSwap(tos, toe);
218955888e44171ffd48b591d19256884a969fe4da17caryclark    }
219055888e44171ffd48b591d19256884a969fe4da17caryclark    do {
219155888e44171ffd48b591d19256884a969fe4da17caryclark        double lcs, lce, los, loe;
219255888e44171ffd48b591d19256884a969fe4da17caryclark        if (coinSeg == list->coinPtTStart()->segment()) {
219355888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppSeg != list->oppPtTStart()->segment()) {
219455888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
219555888e44171ffd48b591d19256884a969fe4da17caryclark            }
219655888e44171ffd48b591d19256884a969fe4da17caryclark            lcs = list->coinPtTStart()->fT;
219755888e44171ffd48b591d19256884a969fe4da17caryclark            lce = list->coinPtTEnd()->fT;
219855888e44171ffd48b591d19256884a969fe4da17caryclark            los = list->oppPtTStart()->fT;
219955888e44171ffd48b591d19256884a969fe4da17caryclark            loe = list->oppPtTEnd()->fT;
220055888e44171ffd48b591d19256884a969fe4da17caryclark            if (los > loe) {
220155888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(los, loe);
220255888e44171ffd48b591d19256884a969fe4da17caryclark            }
220355888e44171ffd48b591d19256884a969fe4da17caryclark        } else if (coinSeg == list->oppPtTStart()->segment()) {
220455888e44171ffd48b591d19256884a969fe4da17caryclark            if (oppSeg != list->coinPtTStart()->segment()) {
220555888e44171ffd48b591d19256884a969fe4da17caryclark                continue;
220655888e44171ffd48b591d19256884a969fe4da17caryclark            }
220755888e44171ffd48b591d19256884a969fe4da17caryclark            lcs = list->oppPtTStart()->fT;
220855888e44171ffd48b591d19256884a969fe4da17caryclark            lce = list->oppPtTEnd()->fT;
220955888e44171ffd48b591d19256884a969fe4da17caryclark            if (lcs > lce) {
221055888e44171ffd48b591d19256884a969fe4da17caryclark                SkTSwap(lcs, lce);
221155888e44171ffd48b591d19256884a969fe4da17caryclark            }
221255888e44171ffd48b591d19256884a969fe4da17caryclark            los = list->coinPtTStart()->fT;
221355888e44171ffd48b591d19256884a969fe4da17caryclark            loe = list->coinPtTEnd()->fT;
221455888e44171ffd48b591d19256884a969fe4da17caryclark        } else {
221555888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
221655888e44171ffd48b591d19256884a969fe4da17caryclark        }
221755888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(tce < lcs || lce < tcs);
221855888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(toe < los || loe < tos);
221955888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((list = list->next()));
222055888e44171ffd48b591d19256884a969fe4da17caryclark}
222155888e44171ffd48b591d19256884a969fe4da17caryclark
222255888e44171ffd48b591d19256884a969fe4da17caryclark
222355888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt,
2224ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkPathOpsDebug::GlitchLog* log) {
222555888e44171ffd48b591d19256884a969fe4da17caryclark    // check for overlapping coincident spans
222655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* test = head;
222755888e44171ffd48b591d19256884a969fe4da17caryclark    while (test) {
222855888e44171ffd48b591d19256884a969fe4da17caryclark        const SkCoincidentSpans* next = test->next();
2229ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        DebugCheckOverlap(test, next, log);
2230ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        DebugCheckOverlap(test, opt, log);
223155888e44171ffd48b591d19256884a969fe4da17caryclark        test = next;
223255888e44171ffd48b591d19256884a969fe4da17caryclark    }
223355888e44171ffd48b591d19256884a969fe4da17caryclark}
223455888e44171ffd48b591d19256884a969fe4da17caryclark
223555888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt,
2236ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkPathOpsDebug::GlitchLog* log) {
223755888e44171ffd48b591d19256884a969fe4da17caryclark    // look for pts inside coincident spans that are not inside the opposite spans
223855888e44171ffd48b591d19256884a969fe4da17caryclark    const SkCoincidentSpans* coin = head;
223955888e44171ffd48b591d19256884a969fe4da17caryclark    while (coin) {
224055888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(),
224155888e44171ffd48b591d19256884a969fe4da17caryclark                coin->oppPtTStart()->segment()));
224255888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart());
224355888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd());
224455888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart());
224555888e44171ffd48b591d19256884a969fe4da17caryclark        SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd());
22466c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark        coin = coin->next();
22476c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    }
2248ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugCheckOverlapTop(head, opt, log);
22496c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark}
22506c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif
22516c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark
22526c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugValidate() const {
22536c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if DEBUG_COINCIDENCE
2254ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugValidate(fHead, fTop, nullptr);
2255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugValidate(fTop, nullptr, nullptr);
22566c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif
22576c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark}
22586c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark
2259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
22606c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt,
2261ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        SkPathOpsDebug::GlitchLog* log) {
22626c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    // look for pts inside coincident spans that are not inside the opposite spans
22636c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    const SkCoincidentSpans* coin = head;
22646c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    while (coin) {
22656c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark        DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(),
226655888e44171ffd48b591d19256884a969fe4da17caryclark                coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(),
2267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log);
22686c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark        DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(),
226955888e44171ffd48b591d19256884a969fe4da17caryclark                coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(),
2270ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                log);
227155888e44171ffd48b591d19256884a969fe4da17caryclark        coin = coin->next();
227255888e44171ffd48b591d19256884a969fe4da17caryclark    }
2273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugCheckOverlapTop(head, opt, log);
227455888e44171ffd48b591d19256884a969fe4da17caryclark}
227555888e44171ffd48b591d19256884a969fe4da17caryclark#endif
227655888e44171ffd48b591d19256884a969fe4da17caryclark
22776c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugCheckBetween() const {
227855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
22796c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    if (fGlobalState->debugCheckHealth()) {
22806c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark        return;
22816c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark    }
2282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugCheckBetween(fHead, fTop, nullptr);
2283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugCheckBetween(fTop, nullptr, nullptr);
228455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
228555888e44171ffd48b591d19256884a969fe4da17caryclark}
228655888e44171ffd48b591d19256884a969fe4da17caryclark
2287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
2288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugCheckHealth(SkPathOpsDebug::GlitchLog* log) const {
2289ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSegment* segment = &fHead;
2290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
2291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        segment->debugCheckHealth(log);
2292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((segment = segment->next()));
229355888e44171ffd48b591d19256884a969fe4da17caryclark}
2294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
2295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCheckValid(SkPathOpsDebug::GlitchLog* log) const {
2296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE
2297ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugValidate(fHead, fTop, log);
2298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    DebugValidate(fTop, nullptr, log);
229955888e44171ffd48b591d19256884a969fe4da17caryclark#endif
2300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
230155888e44171ffd48b591d19256884a969fe4da17caryclark
2302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const {
2303ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkCoincidentSpans* coin = fHead;
2304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (!coin) {
2305ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        return;
2306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    }
230726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
2308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        coin->debugCorrectEnds(log);
2309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((coin = coin->next()));
231026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
231126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
231255888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence()
2313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const {
231455888e44171ffd48b591d19256884a969fe4da17caryclark//    SkASSERT(fCount > 0);
231526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = &fHead;
231655888e44171ffd48b591d19256884a969fe4da17caryclark//    bool result = false;
231726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
2318e47ae2998c1cf944db5743a416583dd0f042b6d9Cary Clark        if (segment->debugMissingCoincidence(log), false) {
231955888e44171ffd48b591d19256884a969fe4da17caryclark//          result = true;
232055888e44171ffd48b591d19256884a969fe4da17caryclark        }
232155888e44171ffd48b591d19256884a969fe4da17caryclark        segment = segment->next();
232255888e44171ffd48b591d19256884a969fe4da17caryclark    } while (segment);
232355888e44171ffd48b591d19256884a969fe4da17caryclark    return;
232426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
2325ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
2326ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveMultiples(SkPathOpsDebug::GlitchLog* log) const {
2327ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkASSERT(fCount > 0);
2328ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSegment* segment = &fHead;
2329ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
2330ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        if (segment->debugMoveMultiples(log), false) {
2331ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            return;
2332ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        }
2333ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((segment = segment->next()));
2334ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
2335ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
2336ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark
2337ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const {
2338ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkASSERT(fCount > 0);
2339ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    const SkOpSegment* segment = &fHead;
2340ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    do {
2341ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        segment->debugMoveNearby(log);
2342ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    } while ((segment = segment->next()));
2343ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark}
234426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
234526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
2346025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2347025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugResetCoinT() const {
2348025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugBaseIndex = -1;
2349025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugBaseMin = 1;
2350025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugBaseMax = -1;
2351025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugLastIndex = -1;
2352025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugLastMin = 1;
2353025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    fDebugLastMax = -1;
2354025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
2355025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
2356025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
23574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const {
2358025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2359025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    {
2360025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        const SkOpSpanBase* span = &fHead;
2361025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        do {
2362025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark            span->debugResetCoinT();
2363025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        } while (!span->final() && (span = span->upCast()->next()));
2364025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        span = &fHead;
2365025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        int index = 0;
2366025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        do {
2367025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark            span->debugSetCoinT(index++);
2368025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        } while (!span->final() && (span = span->upCast()->next()));
2369025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    }
2370025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
237155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
237255888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
237355888e44171ffd48b591d19256884a969fe4da17caryclark        return;
237455888e44171ffd48b591d19256884a969fe4da17caryclark    }
237555888e44171ffd48b591d19256884a969fe4da17caryclark#endif
23764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE
237754359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* span = &fHead;
237854359294a7c9dc54802d512a5d891a35c1663392caryclark    double lastT = -1;
237996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpSpanBase* prev = nullptr;
238054359294a7c9dc54802d512a5d891a35c1663392caryclark    int count = 0;
23814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int done = 0;
238254359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
238354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!span->final()) {
238454359294a7c9dc54802d512a5d891a35c1663392caryclark            ++count;
238554359294a7c9dc54802d512a5d891a35c1663392caryclark            done += span->upCast()->done() ? 1 : 0;
238654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
238754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(span->segment() == this);
238854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev->upCast()->next() == span);
238954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev == span->prev());
239054359294a7c9dc54802d512a5d891a35c1663392caryclark        prev = span;
239154359294a7c9dc54802d512a5d891a35c1663392caryclark        double t = span->ptT()->fT;
239254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastT < t);
239354359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = t;
239454359294a7c9dc54802d512a5d891a35c1663392caryclark        span->debugValidate();
239554359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (!span->final() && (span = span->upCast()->next()));
239654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(count == fCount);
239754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(done == fDoneCount);
239808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    SkASSERT(count >= fDoneCount);
239954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(span->final());
240054359294a7c9dc54802d512a5d891a35c1663392caryclark    span->debugValidate();
240154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
240254359294a7c9dc54802d512a5d891a35c1663392caryclark}
240354359294a7c9dc54802d512a5d891a35c1663392caryclark
2404ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
240530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
240630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with addOpp()
2407ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugAddOpp(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const {
240830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT());
240930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    if (!oppPrev) {
241055888e44171ffd48b591d19256884a969fe4da17caryclark        return;
241126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
2412ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugMergeMatches(log, opp);
241330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    this->ptT()->debugAddOpp(opp->ptT(), oppPrev);
2414ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCheckForCollapsedCoincidence(log);
241526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
241626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
241755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence()
2418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* log) const {
241955888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpCoincidence* coins = this->globalState()->coincidence();
242055888e44171ffd48b591d19256884a969fe4da17caryclark    if (coins->isEmpty()) {
242155888e44171ffd48b591d19256884a969fe4da17caryclark        return;
242255888e44171ffd48b591d19256884a969fe4da17caryclark    }
242355888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span
242455888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop
242555888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span
242655888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* head = this->ptT();
242755888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* test = head;
242826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
242955888e44171ffd48b591d19256884a969fe4da17caryclark        if (!test->coincident()) {
243055888e44171ffd48b591d19256884a969fe4da17caryclark            continue;
243126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
2432ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark        coins->debugMarkCollapsed(log, test);
243355888e44171ffd48b591d19256884a969fe4da17caryclark    } while ((test = test->next()) != head);
243426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
243555888e44171ffd48b591d19256884a969fe4da17caryclark#endif
243626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
243754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const {
243854359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
243954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* next = this;
244054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* nextCoin;
244154359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
244254359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoinEnd;
244354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin);
244454359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
244554359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* checkCoin = this->fCoinEnd;
244654359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* innerCoin = checkCoin;
244754359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
244854359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoinEnd;
244954359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
245054359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident end loop ***\n");
245154359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
245254359294a7c9dc54802d512a5d891a35c1663392caryclark                }
245354359294a7c9dc54802d512a5d891a35c1663392caryclark            }
245454359294a7c9dc54802d512a5d891a35c1663392caryclark        }
245554359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
245654359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
245754359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
245854359294a7c9dc54802d512a5d891a35c1663392caryclark}
245954359294a7c9dc54802d512a5d891a35c1663392caryclark
2460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
246155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd()
2462ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const {
246355888e44171ffd48b591d19256884a969fe4da17caryclark    if (containsCoinEnd(coin)) {
246455888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(coin->containsCoinEnd(this));
246555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
246655888e44171ffd48b591d19256884a969fe4da17caryclark    }
246755888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
246855888e44171ffd48b591d19256884a969fe4da17caryclark//     SkASSERT(this != coin);
2469ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    log->record(SkPathOpsDebug::kMarkCoinEnd_Glitch, this, coin);
247055888e44171ffd48b591d19256884a969fe4da17caryclark//     coin->fCoinEnd = this->fCoinEnd;
247155888e44171ffd48b591d19256884a969fe4da17caryclark//     this->fCoinEnd = coinNext;
247255888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
247355888e44171ffd48b591d19256884a969fe4da17caryclark}
247455888e44171ffd48b591d19256884a969fe4da17caryclark
247530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with mergeMatches()
247630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Look to see if pt-t linked list contains same segment more than once
247730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if so, and if each pt-t is directly pointed to by spans in that segment,
247830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// merge them
247930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// keep the points, but remove spans so that the segment doesn't have 2 or more
248030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// spans pointing to the same pt-t loop at different loop elements
2481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugMergeMatches(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const {
248230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkOpPtT* test = &fPtT;
248330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkOpPtT* testNext;
248430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    const SkOpPtT* stop = test;
248530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    do {
248630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        testNext = test->next();
248730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        if (test->deleted()) {
248830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            continue;
248930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        }
249030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        const SkOpSpanBase* testBase = test->span();
249130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        SkASSERT(testBase->ptT() == test);
249230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        const SkOpSegment* segment = test->segment();
249330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        if (segment->done()) {
249430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            continue;
249530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        }
249630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        const SkOpPtT* inner = opp->ptT();
249730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        const SkOpPtT* innerStop = inner;
249830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        do {
249930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            if (inner->segment() != segment) {
250030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                continue;
250130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            }
250230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            if (inner->deleted()) {
250330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                continue;
250430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            }
250530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            const SkOpSpanBase* innerBase = inner->span();
250630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            SkASSERT(innerBase->ptT() == inner);
250730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            // when the intersection is first detected, the span base is marked if there are
250830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            // more than one point in the intersection.
250930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//            if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) {
251030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                if (!zero_or_one(inner->fT)) {
2511ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                    log->record(SkPathOpsDebug::kMergeMatches_Glitch, innerBase, test);
251230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                } else {
251330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    SkASSERT(inner->fT != test->fT);
251430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    if (!zero_or_one(test->fT)) {
2515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        log->record(SkPathOpsDebug::kMergeMatches_Glitch, testBase, inner);
251630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    } else {
2517ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                        log->record(SkPathOpsDebug::kMergeMatches_Glitch, segment);
251830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                        SkDEBUGCODE(testBase->debugSetDeleted());
251930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                        test->setDeleted();
252030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                        SkDEBUGCODE(innerBase->debugSetDeleted());
252130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//                        inner->setDeleted();
252230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    }
252330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                }
252430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#ifdef SK_DEBUG   // assert if another undeleted entry points to segment
252530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                const SkOpPtT* debugInner = inner;
252630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                while ((debugInner = debugInner->next()) != innerStop) {
252730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    if (debugInner->segment() != segment) {
252830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                        continue;
252930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    }
253030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    if (debugInner->deleted()) {
253130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                        continue;
253230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    }
253330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                    SkOPASSERT(0);
253430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                }
253530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#endif
253630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark                break;
253730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark//            }
253830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark            break;
253930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark        } while ((inner = inner->next()) != innerStop);
254030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark    } while ((test = testNext) != stop);
2541ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    this->debugCheckForCollapsedCoincidence(log);
254230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark}
254330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark
254455888e44171ffd48b591d19256884a969fe4da17caryclark#endif
254526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
2546025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugResetCoinT() const {
2547025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2548025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    const SkOpPtT* ptT = &fPtT;
2549025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    do {
2550025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        ptT->debugResetCoinT();
2551025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        ptT = ptT->next();
2552025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    } while (ptT != &fPtT);
2553025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
2554025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
2555025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
2556025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugSetCoinT(int index) const {
2557025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2558025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    const SkOpPtT* ptT = &fPtT;
2559025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    do {
2560025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        if (!ptT->deleted()) {
2561025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark            ptT->debugSetCoinT(index);
2562025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        }
2563025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark        ptT = ptT->next();
2564025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    } while (ptT != &fPtT);
2565025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
2566025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
2567025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
256826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const {
256926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* end = *endPtr;
257026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() == end->segment());
257126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* result;
257226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (t() < end->t()) {
257326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = this;
257426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } else {
257526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = end;
257626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        *endPtr = this;
257726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
257826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return result->upCast();
257926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
258026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
258154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const {
258255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
258355888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
258455888e44171ffd48b591d19256884a969fe4da17caryclark        return;
258555888e44171ffd48b591d19256884a969fe4da17caryclark    }
258655888e44171ffd48b591d19256884a969fe4da17caryclark#endif
258754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
258854359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* ptT = &fPtT;
258954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(ptT->span() == this);
259054359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
259154359294a7c9dc54802d512a5d891a35c1663392caryclark//        SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt));
259254359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT->debugValidate();
259354359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT = ptT->next();
259454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (ptT != &fPtT);
259554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->debugCoinEndLoopCheck());
259654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final()) {
259754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(this->upCast()->debugCoinLoopCheck());
259854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
259954359294a7c9dc54802d512a5d891a35c1663392caryclark    if (fFromAngle) {
260054359294a7c9dc54802d512a5d891a35c1663392caryclark        fFromAngle->debugValidate();
260154359294a7c9dc54802d512a5d891a35c1663392caryclark    }
260254359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final() && this->upCast()->toAngle()) {
260354359294a7c9dc54802d512a5d891a35c1663392caryclark        this->upCast()->toAngle()->debugValidate();
260454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
26054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
260654359294a7c9dc54802d512a5d891a35c1663392caryclark}
260754359294a7c9dc54802d512a5d891a35c1663392caryclark
260854359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const {
260954359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
261054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* next = this;
261154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* nextCoin;
261254359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
261354359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoincident;
261454359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin);
261554359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
261654359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* checkCoin = this->fCoincident;
261754359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* innerCoin = checkCoin;
261854359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
261954359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoincident;
262054359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
262154359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident loop ***\n");
262254359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
262354359294a7c9dc54802d512a5d891a35c1663392caryclark                }
262454359294a7c9dc54802d512a5d891a35c1663392caryclark            }
262554359294a7c9dc54802d512a5d891a35c1663392caryclark        }
262654359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
262754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
262854359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
262954359294a7c9dc54802d512a5d891a35c1663392caryclark}
263054359294a7c9dc54802d512a5d891a35c1663392caryclark
2631ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
263255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header
2633ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const {
263455888e44171ffd48b591d19256884a969fe4da17caryclark    if (containsCoincidence(coin)) {
263555888e44171ffd48b591d19256884a969fe4da17caryclark//         SkASSERT(coin->containsCoincidence(this));
263655888e44171ffd48b591d19256884a969fe4da17caryclark        return;
263755888e44171ffd48b591d19256884a969fe4da17caryclark    }
263855888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
263955888e44171ffd48b591d19256884a969fe4da17caryclark//     SkASSERT(this != coin);
2640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    log->record(SkPathOpsDebug::kMarkCoinStart_Glitch, this, coin);
264155888e44171ffd48b591d19256884a969fe4da17caryclark//     coin->fCoincident = this->fCoincident;
264255888e44171ffd48b591d19256884a969fe4da17caryclark//     this->fCoincident = coinNext;
264355888e44171ffd48b591d19256884a969fe4da17caryclark    debugValidate();
264455888e44171ffd48b591d19256884a969fe4da17caryclark}
264555888e44171ffd48b591d19256884a969fe4da17caryclark
264655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence()
2647ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped, bool ordered) const {
264855888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->containsCoincidence(segment)) {
264955888e44171ffd48b591d19256884a969fe4da17caryclark        return;
265055888e44171ffd48b591d19256884a969fe4da17caryclark    }
265155888e44171ffd48b591d19256884a969fe4da17caryclark    const SkOpPtT* next = &fPtT;
265255888e44171ffd48b591d19256884a969fe4da17caryclark    while ((next = next->next()) != &fPtT) {
265355888e44171ffd48b591d19256884a969fe4da17caryclark        if (next->segment() == segment) {
2654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            const SkOpSpan* span;
2655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            const SkOpSpanBase* base = next->span();
2656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            if (!ordered) {
2657ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                const SkOpSpanBase* spanEnd = fNext->contains(segment)->span();
2658ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT());
2659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                FAIL_IF(!start->span()->upCastable(), this);
2660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                span = const_cast<SkOpSpan*>(start->span()->upCast());
2661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
2662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            else if (flipped) {
2663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                span = base->prev();
2664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                FAIL_IF(!span, this);
2665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
2666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            else {
2667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                FAIL_IF(!base->upCastable(), this);
2668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark                span = base->upCast();
2669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            }
2670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark            log->record(SkPathOpsDebug::kMarkCoinInsert_Glitch, span);
267155888e44171ffd48b591d19256884a969fe4da17caryclark            return;
267255888e44171ffd48b591d19256884a969fe4da17caryclark        }
267355888e44171ffd48b591d19256884a969fe4da17caryclark    }
2674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN
2675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    log->record(SkPathOpsDebug::kMarkCoinMissing_Glitch, segment, this);
267655888e44171ffd48b591d19256884a969fe4da17caryclark#endif
2677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    return;
267855888e44171ffd48b591d19256884a969fe4da17caryclark}
267955888e44171ffd48b591d19256884a969fe4da17caryclark#endif
268055888e44171ffd48b591d19256884a969fe4da17caryclark
2681624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code
2682624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const {
2683624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    if (!fIsCoincident[0]) {
2684624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkASSERT(!fIsCoincident[1]);
2685624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        return 0;
2686624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
2687624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    int count = 0;
2688624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDEBUGCODE(int count2 = 0;)
2689624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    for (int index = 0; index < fUsed; ++index) {
2690624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[0] & (1 << index)) {
2691624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count;
2692624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
2693624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG
2694624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[1] & (1 << index)) {
2695624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count2;
2696624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
2697624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
2698624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
2699624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkASSERT(count == count2);
2700624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return count;
2701624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
2702624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
270354359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h"
270454359294a7c9dc54802d512a5d891a35c1663392caryclark
270555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp()
270629b2563afb1677515739f1d24fb27733626eca92caryclarkvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const {
270729b2563afb1677515739f1d24fb27733626eca92caryclark    SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext);
270855888e44171ffd48b591d19256884a969fe4da17caryclark    SkASSERT(this != opp);
270955888e44171ffd48b591d19256884a969fe4da17caryclark//    this->fNext = opp;
271029b2563afb1677515739f1d24fb27733626eca92caryclark    SkASSERT(oppPrev != oldNext);
271155888e44171ffd48b591d19256884a969fe4da17caryclark//    oppPrev->fNext = oldNext;
271255888e44171ffd48b591d19256884a969fe4da17caryclark}
271355888e44171ffd48b591d19256884a969fe4da17caryclark
271426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const {
271526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this != check);
271626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
271726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
271826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
271926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
272026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT == check) {
272126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return true;
272226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
272326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
272426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
272526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
272626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
272726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return false;
272826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
272926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
273026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
273126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
273226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
273326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
273426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const {
273526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() != check);
273626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
273726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
273826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
273926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
274026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT->segment() == check) {
274126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return ptT;
274226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
274326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
274426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
274526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
274626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
274726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return nullptr;
274826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
274926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
275026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
275126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
275226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
275326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
27548016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclarkconst SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const {
27558016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark    return fT < end->fT ? end : this;
27568016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark}
27578016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark
275854359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const {
275954359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
276054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* next = this;
276154359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
276254359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
276354359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* checkPtT = this->fNext;
276454359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* innerPtT = checkPtT;
276554359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
276654359294a7c9dc54802d512a5d891a35c1663392caryclark                innerPtT = innerPtT->fNext;
276754359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkPtT == innerPtT) {
276854359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (report) {
276954359294a7c9dc54802d512a5d891a35c1663392caryclark                        SkDebugf("*** bad ptT loop ***\n");
277054359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
277154359294a7c9dc54802d512a5d891a35c1663392caryclark                    return loop;
277254359294a7c9dc54802d512a5d891a35c1663392caryclark                }
27734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
27744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
277526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // there's nothing wrong with extremely large loop counts -- but this may appear to hang
277626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // by taking a very long time to figure out that no loop entry is a duplicate
277726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // -- and it's likely that a large loop count is indicative of a bug somewhere
277826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (++loop > 1000) {
277926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("*** loop count exceeds 1000 ***\n");
278026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return 1000;
278126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
278254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = next->fNext) && next != this);
278354359294a7c9dc54802d512a5d891a35c1663392caryclark    return 0;
278454359294a7c9dc54802d512a5d891a35c1663392caryclark}
278554359294a7c9dc54802d512a5d891a35c1663392caryclark
278629b2563afb1677515739f1d24fb27733626eca92caryclarkconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const {
278729b2563afb1677515739f1d24fb27733626eca92caryclark    return this->oppPrev(const_cast<SkOpPtT*>(opp));
278829b2563afb1677515739f1d24fb27733626eca92caryclark}
278929b2563afb1677515739f1d24fb27733626eca92caryclark
2790025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugResetCoinT() const {
2791025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2792025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    this->segment()->debugResetCoinT();
2793025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
2794025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
2795025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
2796025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugSetCoinT(int index) const {
2797025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER
2798025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark    this->segment()->debugSetCoinT(index, fT);
2799025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif
2800025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark}
2801025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark
280254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const {
280355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE
280455888e44171ffd48b591d19256884a969fe4da17caryclark    if (this->globalState()->debugCheckHealth()) {
280555888e44171ffd48b591d19256884a969fe4da17caryclark        return;
280655888e44171ffd48b591d19256884a969fe4da17caryclark    }
280755888e44171ffd48b591d19256884a969fe4da17caryclark#endif
280854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
2809ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    SkOpPhase phase = contour()->globalState()->phase();
2810ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark    if (phase == SkOpPhase::kIntersecting || phase == SkOpPhase::kFixWinding) {
281154359294a7c9dc54802d512a5d891a35c1663392caryclark        return;
28124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
281354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext);
281454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext != this);
281554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext->fNext);
281654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(debugLoopLimit(false) == 0);
28174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
28184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
28191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
28201049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) {
28211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (num == (int) num) {
28221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%d", (int) num);
28231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    } else {
28241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkString str;
28251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.printf("%1.9g", num);
28261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        int width = (int) str.size();
28271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* cStr = str.c_str();
28281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        while (cStr[width - 1] == '0') {
28291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            --width;
28301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
28311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.resize(width);
28321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%sf", str.c_str());
28331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
28341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
28351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
28361049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) {
28371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    for (int index = 0; index < count; ++index) {
28381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fX);
28391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf(", ");
28401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fY);
28411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (index + 1 < count) {
28421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf(", ");
28431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
28441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
28451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
28461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
28471049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) {
28481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    uint8_t verb;
28491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPoint pts[4];
28501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
28511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        switch (verb) {
28521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kMove_Verb:
28531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.moveTo(", pathName);
28541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[0], 1);
28551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
28561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                continue;
28571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kLine_Verb:
28581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.lineTo(", pathName);
28591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 1);
28601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
28611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
28621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kQuad_Verb:
28631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.quadTo(", pathName);
28641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
28651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
28661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
28671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kConic_Verb:
28681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.conicTo(", pathName);
28691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
28701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(", %1.9gf);\n", iter.conicWeight());
28711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
28721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kCubic_Verb:
28731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.cubicTo(", pathName);
28741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 3);
28751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
28761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
28771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kClose_Verb:
28781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.close();\n", pathName);
28791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
28801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            default:
28811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDEBUGFAIL("bad verb");
28821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                return;
28831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
28841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
28851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
28861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
28871049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = {
28881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kWinding_FillType",
28891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kEvenOdd_FillType",
28901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseWinding_FillType",
28911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseEvenOdd_FillType"
28921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
28931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
28941049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) {
28951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::RawIter iter(path);
28961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0
28971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION
289896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0;
28991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (rectCount > 0) {
29001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkRect> rects;
29011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkPath::Direction> directions;
29021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        rects.setCount(rectCount);
29031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        directions.setCount(rectCount);
29041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        path.rectContours(rects.begin(), directions.begin());
29051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        for (int contour = 0; contour < rectCount; ++contour) {
29061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            const SkRect& rect = rects[contour];
29071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
29081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
29091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
29101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
29111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        return;
29121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
29131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif
29141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::FillType fillType = path.getFillType();
29151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType);
29161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (includeDeclaration) {
29171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("    SkPath %s;\n", name);
29181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
29191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]);
29201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    iter.setPath(path);
29211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    showPathContours(iter, name);
29221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
29231326068147ee60de138061a3fc1157fcfd5d017bcaryclark
2924918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY
29251326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkData.h"
29261326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkStream.h"
29271326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29281326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) {
29291326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkDynamicMemoryWStream wStream;
29301326068147ee60de138061a3fc1157fcfd5d017bcaryclark    path.dump(&wStream, force, dumpAsHex);
29311326068147ee60de138061a3fc1157fcfd5d017bcaryclark    sk_sp<SkData> data(wStream.detachAsData());
29321326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data());
29331326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
29341326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29351326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int dumpID = 0;
29361326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29371326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(const SkPath& one, const SkPath& two, SkPathOp op,
29381326068147ee60de138061a3fc1157fcfd5d017bcaryclark        const char* testName) {
29391326068147ee60de138061a3fc1157fcfd5d017bcaryclark    FILE* file = sk_fopen("op_dump.txt", kWrite_SkFILE_Flag);
29401326068147ee60de138061a3fc1157fcfd5d017bcaryclark    DumpOp(file, one, two, op, testName);
29411326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
29421326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29431326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op,
29441326068147ee60de138061a3fc1157fcfd5d017bcaryclark        const char* testName) {
29451326068147ee60de138061a3fc1157fcfd5d017bcaryclark    const char* name = testName ? testName : "op";
29461326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file,
29471326068147ee60de138061a3fc1157fcfd5d017bcaryclark            "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n",
29481326068147ee60de138061a3fc1157fcfd5d017bcaryclark            name, ++dumpID);
29491326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    SkPath path;\n");
29501326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    path.setFillType((SkPath::FillType) %d);\n", one.getFillType());
29511326068147ee60de138061a3fc1157fcfd5d017bcaryclark    dump_path(file, one, false, true);
29521326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    SkPath path1(path);\n");
29531326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    path.reset();\n");
29541326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    path.setFillType((SkPath::FillType) %d);\n", two.getFillType());
29551326068147ee60de138061a3fc1157fcfd5d017bcaryclark    dump_path(file, two, false, true);
29561326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    SkPath path2(path);\n");
29571326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op);
29581326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "}\n\n");
29591326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fclose(file);
29601326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
29611326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29621326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(const SkPath& path, const char* testName) {
29631326068147ee60de138061a3fc1157fcfd5d017bcaryclark    FILE* file = sk_fopen("simplify_dump.txt", kWrite_SkFILE_Flag);
29641326068147ee60de138061a3fc1157fcfd5d017bcaryclark    DumpSimplify(file, path, testName);
29651326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
29661326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29671326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(FILE* file, const SkPath& path, const char* testName) {
29681326068147ee60de138061a3fc1157fcfd5d017bcaryclark    const char* name = testName ? testName : "simplify";
29691326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file,
29701326068147ee60de138061a3fc1157fcfd5d017bcaryclark            "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n",
29711326068147ee60de138061a3fc1157fcfd5d017bcaryclark            name, ++dumpID);
29721326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    SkPath path;\n");
29731326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    path.setFillType((SkPath::FillType) %d);\n", path.getFillType());
29741326068147ee60de138061a3fc1157fcfd5d017bcaryclark    dump_path(file, path, false, true);
29751326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "    testSimplify(reporter, path, filename);\n");
29761326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fprintf(file, "}\n\n");
29771326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fclose(file);
29781326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
29791326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29801326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkBitmap.h"
29811326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkCanvas.h"
29821326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkPaint.h"
29831326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29841326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitWidth = 64;
29851326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitHeight = 64;
29861326068147ee60de138061a3fc1157fcfd5d017bcaryclark
29871326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void debug_scale_matrix(const SkPath& one, const SkPath* two, SkMatrix& scale) {
29881326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkRect larger = one.getBounds();
29891326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (two) {
29901326068147ee60de138061a3fc1157fcfd5d017bcaryclark        larger.join(two->getBounds());
29911326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
29921326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar largerWidth = larger.width();
29931326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (largerWidth < 4) {
29941326068147ee60de138061a3fc1157fcfd5d017bcaryclark        largerWidth = 4;
29951326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
29961326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar largerHeight = larger.height();
29971326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (largerHeight < 4) {
29981326068147ee60de138061a3fc1157fcfd5d017bcaryclark        largerHeight = 4;
29991326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
30001326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar hScale = (bitWidth - 2) / largerWidth;
30011326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar vScale = (bitHeight - 2) / largerHeight;
30021326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scale.reset();
30031326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scale.preScale(hScale, vScale);
30041326068147ee60de138061a3fc1157fcfd5d017bcaryclark    larger.fLeft *= hScale;
30051326068147ee60de138061a3fc1157fcfd5d017bcaryclark    larger.fRight *= hScale;
30061326068147ee60de138061a3fc1157fcfd5d017bcaryclark    larger.fTop *= vScale;
30071326068147ee60de138061a3fc1157fcfd5d017bcaryclark    larger.fBottom *= vScale;
30081326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft
30091326068147ee60de138061a3fc1157fcfd5d017bcaryclark            : 16000 < larger.fRight ? 16000 - larger.fRight : 0;
30101326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop
30111326068147ee60de138061a3fc1157fcfd5d017bcaryclark            : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0;
30121326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scale.preTranslate(dx, dy);
30131326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
30141326068147ee60de138061a3fc1157fcfd5d017bcaryclark
30151326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) {
30161326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (bits.width() == 0) {
30171326068147ee60de138061a3fc1157fcfd5d017bcaryclark        bits.allocN32Pixels(bitWidth * 2, bitHeight);
30181326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
30191326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkCanvas canvas(bits);
30201326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.drawColor(SK_ColorWHITE);
30211326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPaint paint;
30221326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.save();
30231326068147ee60de138061a3fc1157fcfd5d017bcaryclark    const SkRect& bounds1 = one.getBounds();
30241326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
30251326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.drawPath(one, paint);
30261326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.restore();
30271326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.save();
30281326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
30291326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.drawPath(two, paint);
30301326068147ee60de138061a3fc1157fcfd5d017bcaryclark    canvas.restore();
30311326068147ee60de138061a3fc1157fcfd5d017bcaryclark    int errors = 0;
30321326068147ee60de138061a3fc1157fcfd5d017bcaryclark    for (int y = 0; y < bitHeight - 1; ++y) {
30331326068147ee60de138061a3fc1157fcfd5d017bcaryclark        uint32_t* addr1 = bits.getAddr32(0, y);
30341326068147ee60de138061a3fc1157fcfd5d017bcaryclark        uint32_t* addr2 = bits.getAddr32(0, y + 1);
30351326068147ee60de138061a3fc1157fcfd5d017bcaryclark        uint32_t* addr3 = bits.getAddr32(bitWidth, y);
30361326068147ee60de138061a3fc1157fcfd5d017bcaryclark        uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
30371326068147ee60de138061a3fc1157fcfd5d017bcaryclark        for (int x = 0; x < bitWidth - 1; ++x) {
30381326068147ee60de138061a3fc1157fcfd5d017bcaryclark            // count 2x2 blocks
30391326068147ee60de138061a3fc1157fcfd5d017bcaryclark            bool err = addr1[x] != addr3[x];
30401326068147ee60de138061a3fc1157fcfd5d017bcaryclark            if (err) {
30411326068147ee60de138061a3fc1157fcfd5d017bcaryclark                errors += addr1[x + 1] != addr3[x + 1]
30421326068147ee60de138061a3fc1157fcfd5d017bcaryclark                        && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
30431326068147ee60de138061a3fc1157fcfd5d017bcaryclark            }
30441326068147ee60de138061a3fc1157fcfd5d017bcaryclark        }
30451326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
30461326068147ee60de138061a3fc1157fcfd5d017bcaryclark    return errors;
30471326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
30481326068147ee60de138061a3fc1157fcfd5d017bcaryclark
30491326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op) {
30501326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkDebugf("// Op did not expect failure\n");
30511326068147ee60de138061a3fc1157fcfd5d017bcaryclark    DumpOp(stderr, one, two, op, "opTest");
30521326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fflush(stderr);
30531326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
30541326068147ee60de138061a3fc1157fcfd5d017bcaryclark
30551326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op,
30561326068147ee60de138061a3fc1157fcfd5d017bcaryclark        const SkPath& result) {
30571326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath pathOut, scaledPathOut;
30581326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkRegion rgnA, rgnB, openClip, rgnOut;
30591326068147ee60de138061a3fc1157fcfd5d017bcaryclark    openClip.setRect(-16000, -16000, 16000, 16000);
30601326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnA.setPath(one, openClip);
30611326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnB.setPath(two, openClip);
30621326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnOut.op(rgnA, rgnB, (SkRegion::Op) op);
30631326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnOut.getBoundaryPath(&pathOut);
30641326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkMatrix scale;
30651326068147ee60de138061a3fc1157fcfd5d017bcaryclark    debug_scale_matrix(one, &two, scale);
30661326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
30671326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath scaledA, scaledB;
30681326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledA.addPath(one, scale);
30691326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledA.setFillType(one.getFillType());
30701326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledB.addPath(two, scale);
30711326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledB.setFillType(two.getFillType());
30721326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnA.setPath(scaledA, openClip);
30731326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnB.setPath(scaledB, openClip);
30741326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op);
30751326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnOut.getBoundaryPath(&scaledPathOut);
30761326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkBitmap bitmap;
30771326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath scaledOut;
30781326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledOut.addPath(result, scale);
30791326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledOut.setFillType(result.getFillType());
30801326068147ee60de138061a3fc1157fcfd5d017bcaryclark    int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap);
30811326068147ee60de138061a3fc1157fcfd5d017bcaryclark    const int MAX_ERRORS = 9;
30821326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (errors > MAX_ERRORS) {
30831326068147ee60de138061a3fc1157fcfd5d017bcaryclark        fprintf(stderr, "// Op did not expect errors=%d\n", errors);
30841326068147ee60de138061a3fc1157fcfd5d017bcaryclark        DumpOp(stderr, one, two, op, "opTest");
30851326068147ee60de138061a3fc1157fcfd5d017bcaryclark        fflush(stderr);
30861326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
30871326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
30881326068147ee60de138061a3fc1157fcfd5d017bcaryclark
30891326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportSimplifyFail(const SkPath& path) {
30901326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkDebugf("// Simplify did not expect failure\n");
30911326068147ee60de138061a3fc1157fcfd5d017bcaryclark    DumpSimplify(stderr, path, "simplifyTest");
30921326068147ee60de138061a3fc1157fcfd5d017bcaryclark    fflush(stderr);
30931326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
30941326068147ee60de138061a3fc1157fcfd5d017bcaryclark
30951326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) {
30961326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath pathOut, scaledPathOut;
30971326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkRegion rgnA, openClip, rgnOut;
30981326068147ee60de138061a3fc1157fcfd5d017bcaryclark    openClip.setRect(-16000, -16000, 16000, 16000);
30991326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnA.setPath(path, openClip);
31001326068147ee60de138061a3fc1157fcfd5d017bcaryclark    rgnOut.getBoundaryPath(&pathOut);
31011326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkMatrix scale;
31021326068147ee60de138061a3fc1157fcfd5d017bcaryclark    debug_scale_matrix(path, nullptr, scale);
31031326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkRegion scaledRgnA;
31041326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath scaledA;
31051326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledA.addPath(path, scale);
31061326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledA.setFillType(path.getFillType());
31071326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnA.setPath(scaledA, openClip);
31081326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledRgnA.getBoundaryPath(&scaledPathOut);
31091326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkBitmap bitmap;
31101326068147ee60de138061a3fc1157fcfd5d017bcaryclark    SkPath scaledOut;
31111326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledOut.addPath(result, scale);
31121326068147ee60de138061a3fc1157fcfd5d017bcaryclark    scaledOut.setFillType(result.getFillType());
31131326068147ee60de138061a3fc1157fcfd5d017bcaryclark    int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap);
31141326068147ee60de138061a3fc1157fcfd5d017bcaryclark    const int MAX_ERRORS = 9;
31151326068147ee60de138061a3fc1157fcfd5d017bcaryclark    if (errors > MAX_ERRORS) {
31161326068147ee60de138061a3fc1157fcfd5d017bcaryclark        fprintf(stderr, "// Simplify did not expect errors=%d\n", errors);
31171326068147ee60de138061a3fc1157fcfd5d017bcaryclark        DumpSimplify(stderr, path, "simplifyTest");
31181326068147ee60de138061a3fc1157fcfd5d017bcaryclark        fflush(stderr);
31191326068147ee60de138061a3fc1157fcfd5d017bcaryclark    }
31201326068147ee60de138061a3fc1157fcfd5d017bcaryclark}
31211326068147ee60de138061a3fc1157fcfd5d017bcaryclark
31221326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif
3123