SkPathOpsDebug.cpp revision f2b340fc885ad2a12d2d73974eff9c8f4c94192c
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h"
926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h"
1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h"
1102802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h"
121b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h"
1354359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h"
1454359294a7c9dc54802d512a5d891a35c1663392caryclark
1526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkCoincidentSpans;
1626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
1754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
1854359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail;
1954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
21624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
22624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
23624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount;
24624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
25624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
26624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP
27624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
28624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
29624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
32570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org
34fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0;
35fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0;
36570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
3754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray,
3854359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* span) {
394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int index = 0; index < chaseArray.count(); ++index) {
4054359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* entry = chaseArray[index];
414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (entry == span) {
424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return true;
434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return false;
464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
4726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
4826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
4926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
5026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkenum GlitchType {
5126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddCorruptCoin_Glitch,
5226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddExpandedCoin_Glitch,
5326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kAddMissingCoin_Glitch,
5426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedCoin_Glitch,
5526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedDone_Glitch,
5626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedOppValue_Glitch,
5726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedSpan_Glitch,
5826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kCollapsedWindValue_Glitch,
5926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kDeletedCoin_Glitch,
6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kExpandCoin_Glitch,
6126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMarkCoinEnd_Glitch,
6226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMarkCoinInsert_Glitch,
6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingCoin_Glitch,
6426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingDone_Glitch,
6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMissingIntersection_Glitch,
6626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kMoveMultiple_Glitch,
6726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnaligned_Glitch,
6826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnalignedHead_Glitch,
6926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnalignedTail_Glitch,
7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUndetachedSpan_Glitch,
7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    kUnmergedSpan_Glitch,
7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
7426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic const int kGlitchType_Count = kUnmergedSpan_Glitch + 1;
7526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
7626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch {
7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* fStage;
7826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fBase;
7926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* fSuspect;
8026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* fCoin;
8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* fSegment;
8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fCoinSpan;
8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fEndSpan;
8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppSpan;
8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* fOppEndSpan;
8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double fT;
8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkPoint fPt;
8826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    GlitchType fType;
8926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
9026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog {
9226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SpanGlitch* recordCommon(GlitchType type, const char* stage) {
9326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = fGlitches.push();
9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fStage = stage;
9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = nullptr;
9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = nullptr;
9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoin = nullptr;
9826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = nullptr;
9926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = nullptr;
10026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = nullptr;
10126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = nullptr;
10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = nullptr;
10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fT = SK_ScalarNaN;
10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN };
10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fType = type;
10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return glitch;
10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base,
11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* suspect = NULL) {
11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
11226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
11326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = suspect;
11426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* coinSpan) {
11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
11926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoin = coin;
12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = coinSpan;
12126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base,
12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* seg, double t, SkPoint pt) {
12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSegment = seg;
12826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fT = t;
12926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
13026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
13126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
13226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpSpanBase* base, double t,
13326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkPoint pt) {
13426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
13526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fBase = base;
13626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fT = t;
13726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fPt = pt;
13826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
13926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
14026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* coinSpan, const SkOpPtT* endSpan) {
14226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoin = coin;
14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = coinSpan;
14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = endSpan;
14626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
14726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
14826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin,
14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* suspect) {
15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
15126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fSuspect = suspect;
15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoin = coin;
15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
15526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const SkOpPtT* ptTE,
15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) {
15726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SpanGlitch* glitch = recordCommon(type, stage);
15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fCoinSpan = ptTS;
15926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fEndSpan = ptTE;
16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppSpan = oPtTS;
16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        glitch->fOppEndSpan = oPtTE;
16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkTDArray<SpanGlitch> fGlitches;
16526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark};
16626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    GlitchLog glitches;
16926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpContour* contour = contourList;
17026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpCoincidence* coincidence = contour->globalState()->coincidence();
17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
17226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        contour->debugCheckHealth(id, &glitches);
17326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        contour->debugMissingCoincidence(id, &glitches, coincidence);
17426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((contour = contour->next()));
17526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugFixAligned(id, &glitches);
17626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugAddMissing(id, &glitches);
17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugExpand(id, &glitches);
17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugAddExpanded(id, &glitches);
17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coincidence->debugMark(id, &glitches);
18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    unsigned mask = 0;
18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < glitches.fGlitches.count(); ++index) {
18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SpanGlitch& glitch = glitches.fGlitches[index];
18326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        mask |= 1 << glitch.fType;
18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < kGlitchType_Count; ++index) {
18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(mask & (1 << index) ? "x" : "-");
18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("  %s\n", id);
18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
1914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE
193570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    size_t len = strlen(str);
19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool num = false;
19607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    for (size_t idx = 0; idx < len; ++idx) {
19707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        if (num && str[idx] == 'e') {
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (len + 2 >= bufferLen) {
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                return;
20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            memmove(&str[idx + 2], &str[idx + 1], len - idx);
20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx] = '*';
20307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            str[idx + 1] = '^';
20407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            ++len;
20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        num = str[idx] >= '0' && str[idx] <= '9';
20707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
210570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) {
21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
214570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) {
21507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (wind == SK_MinS32) {
21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("?");
21707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    } else {
21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%d", wind);
21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
22154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif //  defined SK_DEBUG || !FORCE_RELEASE
22254359294a7c9dc54802d512a5d891a35c1663392caryclark
223a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
22407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME
225385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; }
226cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
227385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); }
228a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
229570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) {
23007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    char* num = test + strlen(test);
23107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    while (num[-1] >= '0' && num[-1] <= '9') {
23207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        --num;
23307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
23407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (num[0] == '\0') {
23507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
23607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
23707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    int dec = atoi(num);
23807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    if (dec == 0) {
23907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com        return;
24007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    }
24107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    ++dec;
24207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com    SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec);
243a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com}
244a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif
245570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
2461049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) {
2471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName);
2481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (strcmp("skphealth_com76", functionName) == 0) {
2491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("found it\n");
2501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
2511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
2521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
2531049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = {
2541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kDifference_SkPathOp",
2551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kIntersect_SkPathOp",
2561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kUnion_SkPathOp",
2571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kXor_PathOp",
2581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kReverseDifference_SkPathOp",
2591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
2601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
26103b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) {
26203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark    return gOpStrs[op];
26303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark}
26403b03cad01628146bbb8d4f33c073bd0c77ee558caryclark
2651049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) {
2661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]);
2671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("}\n");
2681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
2691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
2701049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkSK_DECLARE_STATIC_MUTEX(gTestMutex);
2711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
2721049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
2731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* testName) {
2741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkAutoMutexAcquire ac(gTestMutex);
2751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_function_header(testName);
2761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(a, "path", true);
2771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    ShowOnePath(b, "pathB", true);
2781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    show_op(shapeOp, "path", "pathB");
2794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
2804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
28127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h"
28226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h"
28326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h"
28426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
28526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
28626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt,
28726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkIntersectionHelper& wn) {
28826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
28926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index;
29026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) {
29126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
29226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
29326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = i->debugLoopCount(looper);
29426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = wt.segment()->verb();
29526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb();
29626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8);
29726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(),
29826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint));
29926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(),
30026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint));
30126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = wt.weight();
30226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = wn.weight();
30326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
30426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    i->debugResetLoopCount();
30526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
30626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
30726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) {
30826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
30926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) {
31026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
31126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
31226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugLoopCount[index] = local->fDebugLoopCount[index];
31326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2];
31426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1];
31526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4],
31626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                sizeof(SkPoint) * 8);
31726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2];
31826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1];
31926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
32026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    local->debugResetLoopCounts();
32126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
32226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
32326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) {
32426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!verb) {
32526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
32626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
32726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* verbs[] = { "", "line", "quad", "conic", "cubic" };
32826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("%s: {{", verbs[verb]);
32926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int ptCount = SkPathOpsVerbToPoints(verb);
33026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index <= ptCount; ++index) {
33126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint::Dump((&pts)[index]);
33226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (index < ptCount - 1) {
33326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf(", ");
33426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
33526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
33626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}");
33726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (weight != 1) {
33826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf(", ");
33926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (weight == floorf(weight)) {
34026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%.0f", weight);
34126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } else {
34226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%1.9gf", weight);
34326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
34426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
34526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("}\n");
34626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
34726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
34826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() {
34926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const char* loops[] = { "iterations", "coinChecks", "perpCalcs" };
35026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDebugf("\n");
35126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) {
35226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]);
35326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4],
35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2]);
35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4],
35626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                fDebugWorstWeight[index * 2 + 1]);
35726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
35926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
36026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() {
36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
36226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb));
36326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts));
36426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight));
36526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
36626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
36727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
36827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG
36927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const {
37027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE
37127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return FLAGS_runFail;
37227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else
37327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark    return false;
37427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif
37527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark}
37627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif
37727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark
37826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT
37926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) {
38026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    fDebugLoopCount[index]++;
38126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
38226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
38326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const {
38426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return fDebugLoopCount[index];
38526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
38626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
38726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() {
38826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
38926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
39026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
39126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
392624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h"
393624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsQuad.h"
394624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
395624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const {
396624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDCubic cubic;
397624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[0] = fPts[0];
398624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2] = fPts[1];
399624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[3] = fPts[2];
400624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3;
401624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3;
402624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3;
403624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3;
404624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return cubic;
405624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
406624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
407ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() {
408ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    fLeft = fTop = fRight = fBottom = SK_ScalarNaN;
409ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark}
410ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark
4114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h"
412570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h"
413570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
41426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
41526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugAddAlignIntersection(const char* id, SkPathOpsDebug::GlitchLog* log,
41626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT& endPtT, const SkPoint& oldPt,  const SkOpContourHead* contourList) const {
41726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkPoint& newPt = endPtT.fPt;
41826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (newPt == oldPt) {
41926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
42026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
42126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkPoint line[2] = { newPt, oldPt };
42226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkPathOpsBounds lineBounds;
42326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    lineBounds.setBounds(line, 2);
42426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkDLine aLine;
42526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    aLine.set(line);
42626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpContour* current = contourList;
42726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
42826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!SkPathOpsBounds::Intersects(current->bounds(), lineBounds)) {
42926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
43026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
43126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* segment = current->first();
43226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {
43326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!SkPathOpsBounds::Intersects(segment->bounds(), lineBounds)) {
43426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
43526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
43626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (newPt == segment->fPts[0]) {
43726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
43826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
43926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (newPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) {
44026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
44126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
44226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oldPt == segment->fPts[0]) {
44326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
44426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
44526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oldPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) {
44626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
44726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
44826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (endPtT.debugContains(segment)) {
44926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
45026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
45126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkIntersections i;
45226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            switch (segment->fVerb) {
45326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                case SkPath::kLine_Verb: {
45426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkDLine bLine;
45526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bLine.set(segment->fPts);
45626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    i.intersect(bLine, aLine);
45726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } break;
45826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                case SkPath::kQuad_Verb: {
45926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkDQuad bQuad;
46026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bQuad.set(segment->fPts);
46126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    i.intersect(bQuad, aLine);
46226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } break;
46326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                case SkPath::kConic_Verb: {
46426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkDConic bConic;
46526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bConic.set(segment->fPts, segment->fWeight);
46626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    i.intersect(bConic, aLine);
46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } break;
46826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                case SkPath::kCubic_Verb: {
46926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkDCubic bCubic;
47026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bCubic.set(segment->fPts);
47126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    i.intersect(bCubic, aLine);
47226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } break;
47326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                default:
47426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkASSERT(0);
47526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
47626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (i.used()) {
47726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkASSERT(i.used() == 1);
47826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkASSERT(!zero_or_one(i[0][0]));
47926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkOpSpanBase* checkSpan = fHead.next();
48026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while (!checkSpan->final()) {
48126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (checkSpan->contains(segment)) {
48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        goto nextSegment;
48326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
48426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    checkSpan = checkSpan->upCast()->next();
48526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
48626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kMissingIntersection_Glitch, id, checkSpan, segment, i[0][0], newPt);
48726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
48826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    nextSegment:
48926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            ;
49026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((segment = segment->next()));
49126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((current = current->next()));
49226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
49326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
49426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSegment::debugAddMissing(double t, const SkOpSegment* opp) const {
49526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* existing = nullptr;
49626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* test = &fHead;
49726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double testT;
49826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
49926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if ((testT = test->ptT()->fT) >= t) {
50026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (testT == t) {
50126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                existing = test;
50226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
50326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            break;
50426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
50526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((test = test->upCast()->next()));
50626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return !existing || !existing->debugContains(opp);
50726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
50826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
50926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugAlign(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
51026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* span = &fHead;
51126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!span->aligned()) {
51226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!span->debugAlignedEnd(0, fPts[0])) {
51326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            glitches->record(kUnalignedHead_Glitch, id, span);
51426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
51526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
51626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    while ((span = span->upCast()->next())) {
51726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (span == &fTail) {
51826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            break;
51926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
52026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!span->aligned()) {
52126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            glitches->record(kUnaligned_Glitch, id, span);
52226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
52326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
52426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!span->aligned()) {
52526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        span->debugAlignedEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]);
52626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
52726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (this->collapsed()) {
52826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpan* span = &fHead;
52926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {
53026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (span->windValue()) {
53126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                glitches->record(kCollapsedWindValue_Glitch, id, span);
53226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
53326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (span->oppValue()) {
53426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                glitches->record(kCollapsedOppValue_Glitch, id, span);
53526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
53626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!span->done()) {
53726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                glitches->record(kCollapsedDone_Glitch, id, span);
53826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
53926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((span = span->next()->upCastable()));
54026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
54126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
54226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
54326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
54426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
54526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const {
54626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* base = &fHead;
54726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* span;
54826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
54926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* angle = base->fromAngle();
55026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (angle && angle->fCheckCoincidence) {
55126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
55226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
55326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (base->final()) {
55426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark             break;
55526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
55626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        span = base->upCast();
55726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        angle = span->toAngle();
55826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (angle && angle->fCheckCoincidence) {
55926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            angle->debugCheckNearCoincidence();
56026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
56126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((base = span->next()));
56226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
56326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
56426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
56526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
56626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence
56726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
56826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugMoveMultiples(id, glitches);
56926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugFindCollapsed(id, glitches);
57026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugMoveNearby(id, glitches);
57126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugAlign(id, glitches);
57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    debugAddAlignIntersections(id, glitches, this->globalState()->contourHead());
57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
57526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
57626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugFindCollapsed(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
57726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (fHead.contains(&fTail)) {
57826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpan* span = this->head();
57926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        bool missingDone = false;
58026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {
58126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            missingDone |= !span->done();
58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((span = span->next()->upCastable()));
58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (missingDone) {
58426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            glitches->record(kMissingDone_Glitch, id, &fHead);
58526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
58626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!fHead.debugAlignedEnd(0, fHead.pt())) {
58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            glitches->record(kUnalignedHead_Glitch, id, &fHead);
58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!fTail.aligned()) {
59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            glitches->record(kUnalignedTail_Glitch, id, &fTail);
59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
59654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() {
59796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkOpAngle* result = nullptr;
59854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* span = this->head();
59954359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
60054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->toAngle()) {
601dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkASSERT(!result);
60254359294a7c9dc54802d512a5d891a35c1663392caryclark            result = span->toAngle();
603dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
60454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((span = span->next()->upCastable()));
605dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkASSERT(result);
606dac1d17027dcaa5596885a9f333979418b35001ccaryclark    return result;
607dac1d17027dcaa5596885a9f333979418b35001ccaryclark}
608dac1d17027dcaa5596885a9f333979418b35001ccaryclark
60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log,
61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpCoincidence* coincidences) const {
61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (this->verb() != SkPath::kLine_Verb) {
61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (this->done()) {
61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpan* prior = nullptr;
61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* spanBase = &fHead;
62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(ptT->span() == spanBase);
62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((ptT = ptT->next()) != spanStopPtT) {
62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT->deleted()) {
62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkOpSegment* opp = ptT->span()->segment();
62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//            if (opp->verb() == SkPath::kLine_Verb) {
62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//                continue;
63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark//            }
63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (opp->done()) {
63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!opp->visited()) {
63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (spanBase == &fHead) {
63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* span = spanBase->upCastable();
64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // FIXME?: this assumes that if the opposite segment is coincident then no more
64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // coincidence needs to be detected. This may not be true.
64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (span && span->segment() != opp && span->containsCoincidence(opp)) {
64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) {
64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* priorPtT = nullptr, * priorStopPtT;
65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find prior span containing opp segment
65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* priorOpp = nullptr;
65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* priorTest = spanBase->prev();
65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while (!priorOpp && priorTest) {
65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorStopPtT = priorPtT = priorTest->ptT();
65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((priorPtT = priorPtT->next()) != priorStopPtT) {
65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (priorPtT->deleted()) {
65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        continue;
65926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    SkOpSegment* segment = priorPtT->span()->segment();
66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (segment == opp) {
66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        prior = priorTest;
66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        priorOpp = opp;
66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        break;
66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
66726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                priorTest = priorTest->prev();
66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
66926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!priorOpp) {
67026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
67126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
67226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppStart = prior->ptT();
67326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* oppEnd = spanBase->ptT();
67426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool swapped = priorPtT->fT > ptT->fT;
67526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
67626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
67726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(oppStart, oppEnd);
67826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
67926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool flipped = oppStart->fT > oppEnd->fT;
68026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool coincident = false;
68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) {
68226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                goto swapBack;
68326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
68426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (opp->verb() == SkPath::kLine_Verb) {
68526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppStart->fPt) ||
68626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt)) &&
68726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) ||
68826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt));
68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!coincident) {
69126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000);
69226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
69326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (coincident) {
69426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, oppEnd);
69526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    swapBack:
69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (swapped) {
69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(priorPtT, ptT);
69926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
70026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
70126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next()));
70226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
70326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
70426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
70526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* test = &fHead;
70626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
70726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        int addCount = test->spanAddsCount();
70826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(addCount >= 1);
70926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (addCount == 1) {
71026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
71126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
71226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* startPtT = test->ptT();
71326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* testPtT = startPtT;
71426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {  // iterate through all spans associated with start
71526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppSpan = testPtT->span();
71626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->spanAddsCount() == addCount) {
71726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
71826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
71926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSpan->deleted()) {
72026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
72126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
72226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* oppSegment = oppSpan->segment();
72326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppSegment == this) {
72426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
72526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
72626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            // find range of spans to consider merging
72726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppPrev = oppSpan;
72826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppFirst = oppSpan;
72926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppPrev = oppPrev->prev())) {
73026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppPrev->t(), oppSpan->t())) {
73126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
73226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
73326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->spanAddsCount() == addCount) {
73426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
73526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
73626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppPrev->deleted()) {
73726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
73826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
73926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppFirst = oppPrev;
74026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
74126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppNext = oppSpan;
74226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppLast = oppSpan;
74326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) {
74426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (!roughly_equal(oppNext->t(), oppSpan->t())) {
74526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
74626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
74726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->spanAddsCount() == addCount) {
74826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
74926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
75026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppNext->deleted()) {
75126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
75226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
75326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oppLast = oppNext;
75426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
75526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (oppFirst == oppLast) {
75626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                continue;
75726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
75826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpanBase* oppTest = oppFirst;
75926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            do {
76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (oppTest == oppSpan) {
76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    continue;
76226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
76326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // check to see if the candidate meets specific criteria:
76426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // it contains spans of segments in test's loop but not including 'this'
76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppStartPtT = oppTest->ptT();
76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* oppPtT = oppStartPtT;
76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                while ((oppPtT = oppPtT->next()) != oppStartPtT) {
76826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpSegment* oppPtTSegment = oppPtT->segment();
76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (oppPtTSegment == this) {
77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        goto tryNextSpan;
77126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    const SkOpPtT* matchPtT = startPtT;
77326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    do {
77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        if (matchPtT->segment() == oppPtTSegment) {
77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            goto foundMatch;
77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        }
77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } while ((matchPtT = matchPtT->next()) != startPtT);
77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto tryNextSpan;
77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            foundMatch:  // merge oppTest and oppSpan
78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) {
78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse
78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        SkASSERT(oppSpan != &oppSegment->fTail);
78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        glitches->record(kMoveMultiple_Glitch, id, oppTest, oppSpan);
78426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    } else {
78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppTest);
78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    goto checkNextSpan;
78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        tryNextSpan:
79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                ;
79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next()));
79226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((testPtT = testPtT->next()) != startPtT);
79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkcheckNextSpan:
79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ;
79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((test = test->final() ? nullptr : test->upCast()->next()));
79626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
79726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
79826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* glitches) const {
79926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* spanS = &fHead;
80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
80126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* test = spanS->upCast()->next();
80226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* next;
80326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (spanS->contains(test)) {
80426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!test->final()) {
80526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                glitches->record(kUndetachedSpan_Glitch, id, test, spanS);
80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } else if (spanS != &fHead) {
80726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                glitches->record(kUndetachedSpan_Glitch, id, spanS, test);
80826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
80926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
81026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {  // iterate through all spans associated with start
81126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* startBase = spanS->ptT();
81226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            next = test->final() ? nullptr : test->upCast()->next();
81326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            do {
81426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* testBase = test->ptT();
81526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                do {
81626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (startBase == testBase) {
81726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        goto checkNextSpan;
81826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
81926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (testBase->duplicate()) {
82026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        continue;
82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
82226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) {
82326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        if (test == &this->fTail) {
82426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            if (spanS == &fHead) {
82526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                                glitches->record(kCollapsedSpan_Glitch, id, spanS);
82626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            } else {
82726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                                glitches->record(kUnmergedSpan_Glitch, id, &this->fTail, spanS);
82826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            }
82926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        } else {
83026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            glitches->record(kUnmergedSpan_Glitch, id, spanS, test);
83126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            goto checkNextSpan;
83226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        }
83326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
83426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                } while ((testBase = testBase->next()) != test->ptT());
83526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } while ((startBase = startBase->next()) != spanS->ptT());
83626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    checkNextSpan:
83726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            ;
83826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while ((test = next));
83926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        spanS = spanS->upCast()->next();
84026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (!spanS->final());
84126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
84226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
84326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
8444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() {
8451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    this->init(this->fPts, this->fWeight, this->contour(), this->verb());
8464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
8474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
84854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS
8494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const {
8504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    debugValidate();
8514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    if (done()) {
8524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return;
8534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
8544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int lastId = -1;
8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double lastT = -1;
85654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* span = &fHead;
85754359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
85854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->done()) {
8594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
8604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
8611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (lastId == this->debugID() && lastT == span->t()) {
8624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            continue;
8634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
8641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        lastId = this->debugID();
86554359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = span->t();
8661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%s id=%d", __FUNCTION__, this->debugID());
8674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
8684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
8694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
8704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
8711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (SkPath::kConic_Verb == fVerb) {
8721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf(" %1.9gf", fWeight);
8731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
87454359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpPtT* ptT = span->ptT();
87554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf(") t=%1.9g (%1.9g,%1.9g)", ptT->fT, ptT->fPt.fX, ptT->fPt.fY);
87654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf(" tEnd=%1.9g", span->next()->t());
87754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (span->windSum() == SK_MinS32) {
878624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" windSum=?");
8794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        } else {
880624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" windSum=%d", span->windSum());
881624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
882624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() && span->oppSum() == SK_MinS32) {
883624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppSum=?");
884624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        } else if (span->oppValue() || span->oppSum() != SK_MinS32) {
885624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppSum=%d", span->oppSum());
886624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
887624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDebugf(" windValue=%d", span->windValue());
888624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (span->oppValue() || span->oppSum() != SK_MinS32) {
889624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            SkDebugf(" oppValue=%d", span->oppValue());
8904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
89154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
89254359294a7c9dc54802d512a5d891a35c1663392caryclark   } while ((span = span->next()->upCastable()));
8934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
8944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
8954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
89654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE
89754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) {
89854359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
8991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
9004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
9014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
9024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
9034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
90454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
90554359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t());
90654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
9074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
9084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
90954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
9104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
91154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windSum=");
91254359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
91354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
91454359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
91554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
91654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
91754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d\n", span->windValue());
9184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
9194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
92054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding,
9214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                      int oppWinding) {
92254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = span->ptT()->fPt;
9231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("%s id=%d", fun, this->debugID());
9244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
9254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
9264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
9274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
92854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=",
92954359294a7c9dc54802d512a5d891a35c1663392caryclark            span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding);
93054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (winding == SK_MinS32) {
93154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
93254359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
93354359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", winding);
93454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
93554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" newOppSum=");
93654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (oppWinding == SK_MinS32) {
93754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("?");
93854359294a7c9dc54802d512a5d891a35c1663392caryclark    } else {
93954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", oppWinding);
94054359294a7c9dc54802d512a5d891a35c1663392caryclark    }
94154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" oppSum=");
94254359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->oppSum() == SK_MinS32) {
9434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
9444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
94554359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->oppSum());
9464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
9474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkDebugf(" windSum=");
94854359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->windSum() == SK_MinS32) {
9494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkDebugf("?");
9504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    } else {
95154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("%d", span->windSum());
9524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
95354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue());
9544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
95554359294a7c9dc54802d512a5d891a35c1663392caryclark
9564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
9574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted
95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted.
96026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark   This should be rarely called -- the test below is thorough and time consuming.
96126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark   This checks the distance between start points; the distance between
96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/
96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE
96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const {
96526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpAngle* test = this;
96626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
96726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* testSegment = test->segment();
96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testStartT = test->start()->t();
96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testStartPt = testSegment->dPtAtT(testStartT);
97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testEndT = test->end()->t();
97126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDPoint testEndPt = testSegment->dPtAtT(testEndT);
97226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testLenSq = testStartPt.distanceSquared(testEndPt);
97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID());
97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        double testMidT = (testStartT + testEndT) / 2;
97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpAngle* next = test;
97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((next = next->fNext) != this) {
97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkOpSegment* nextSegment = next->segment();
97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testMidDistSq = testSegment->distSq(testMidT, next);
97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double testEndDistSq = testSegment->distSq(testEndT, next);
98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextStartT = next->start()->t();
98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT);
98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double distSq = testStartPt.distanceSquared(nextStartPt);
98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndT = next->end()->t();
98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidT = (nextStartT + nextEndT) / 2;
98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextMidDistSq = nextSegment->distSq(nextMidT, test);
98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextEndDistSq = nextSegment->distSq(nextEndT, test);
98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq,
98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    testSegment->debugID(), nextSegment->debugID());
98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq);
99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq);
99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq);
99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq);
99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT);
99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double nextLenSq = nextStartPt.distanceSquared(nextEndPt);
99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq);
99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("\n");
99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        test = test->fNext;
99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (test->fNext != this);
100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
100354359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE
100454359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const {
100554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkString result;
100654359294a7c9dc54802d512a5d891a35c1663392caryclark    switch (this->segment()->verb()) {
100754359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kLine_Verb:
100854359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart),
100954359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
101054359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
101154359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kQuad_Verb:
101254359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart),
101354359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
101454359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
10151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        case SkPath::kConic_Verb:
10161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            result.printf(CONIC_DEBUG_STR " id=%d",
10171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    CONIC_DEBUG_DATA(fCurvePart, fCurvePart.fConic.fWeight),
10181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    this->segment()->debugID());
10191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            break;
102054359294a7c9dc54802d512a5d891a35c1663392caryclark        case SkPath::kCubic_Verb:
102154359294a7c9dc54802d512a5d891a35c1663392caryclark            result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart),
102254359294a7c9dc54802d512a5d891a35c1663392caryclark                    this->segment()->debugID());
102354359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
102454359294a7c9dc54802d512a5d891a35c1663392caryclark        default:
102554359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(0);
10261b24933e52f50773de29332387a12721811f3012mtklein    }
102754359294a7c9dc54802d512a5d891a35c1663392caryclark    return result;
102854359294a7c9dc54802d512a5d891a35c1663392caryclark}
102954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
103054359294a7c9dc54802d512a5d891a35c1663392caryclark
1031624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT
103254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const {
103354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
103454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
103554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
103654359294a7c9dc54802d512a5d891a35c1663392caryclark        next->dumpOne(true);
103754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkDebugf("\n");
103854359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
103954359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
104054359294a7c9dc54802d512a5d891a35c1663392caryclark    next = first;
104154359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
104254359294a7c9dc54802d512a5d891a35c1663392caryclark        next->debugValidate();
104354359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
104454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
1045ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
1046ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif
1047ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
104854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const {
104954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
105054359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
105154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = this;
105254359294a7c9dc54802d512a5d891a35c1663392caryclark    int wind = 0;
105354359294a7c9dc54802d512a5d891a35c1663392caryclark    int opp = 0;
105454359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastXor = -1;
105554359294a7c9dc54802d512a5d891a35c1663392caryclark    int lastOppXor = -1;
105654359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
105754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next->unorderable()) {
105854359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
105954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
106054359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpan* minSpan = next->start()->starter(next->end());
106154359294a7c9dc54802d512a5d891a35c1663392caryclark        if (minSpan->windValue() == SK_MinS32) {
106254359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
106354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
106454359294a7c9dc54802d512a5d891a35c1663392caryclark        bool op = next->segment()->operand();
106554359294a7c9dc54802d512a5d891a35c1663392caryclark        bool isXor = next->segment()->isXor();
106654359294a7c9dc54802d512a5d891a35c1663392caryclark        bool oppXor = next->segment()->oppXor();
106754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM));
106854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!DEBUG_LIMIT_WIND_SUM
106954359294a7c9dc54802d512a5d891a35c1663392caryclark                || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM));
107054359294a7c9dc54802d512a5d891a35c1663392caryclark        bool useXor = op ? oppXor : isXor;
107154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastXor == -1 || lastXor == (int) useXor);
107254359294a7c9dc54802d512a5d891a35c1663392caryclark        lastXor = (int) useXor;
1073624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue());
107454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
107554359294a7c9dc54802d512a5d891a35c1663392caryclark            wind &= 1;
107654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
107754359294a7c9dc54802d512a5d891a35c1663392caryclark        useXor = op ? isXor : oppXor;
107854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor);
107954359294a7c9dc54802d512a5d891a35c1663392caryclark        lastOppXor = (int) useXor;
1080624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue());
108154359294a7c9dc54802d512a5d891a35c1663392caryclark        if (useXor) {
108254359294a7c9dc54802d512a5d891a35c1663392caryclark            opp &= 1;
108354359294a7c9dc54802d512a5d891a35c1663392caryclark        }
108454359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->fNext;
108554359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (next && next != first);
1086182b499cd75c971f85cdf52c1827b3c220cc9011caryclark    SkASSERT(wind == 0 || !FLAGS_runFail);
108754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(opp == 0 || !FLAGS_runFail);
108854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
108954359294a7c9dc54802d512a5d891a35c1663392caryclark}
109054359294a7c9dc54802d512a5d891a35c1663392caryclark
109154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const {
109254359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE
109354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* first = this;
109454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpAngle* next = first;
109554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkTDArray<const SkOpAngle*>(angles);
109654359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
1097f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen//        SkASSERT_RELEASE(next->fSegment->debugContains(next));
109854359294a7c9dc54802d512a5d891a35c1663392caryclark        angles.push(next);
109954359294a7c9dc54802d512a5d891a35c1663392caryclark        next = next->next();
110054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next == first) {
110154359294a7c9dc54802d512a5d891a35c1663392caryclark            break;
110254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
1103f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen        SkASSERT_RELEASE(!angles.contains(next));
110454359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!next) {
110554359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
110654359294a7c9dc54802d512a5d891a35c1663392caryclark        }
110754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (true);
110854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
110954359294a7c9dc54802d512a5d891a35c1663392caryclark}
111054359294a7c9dc54802d512a5d891a35c1663392caryclark
111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* log) const {
111426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // for each coincident pair, match the spans
111526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span
111626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = this->fHead;
111726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
111826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        coin = this->fTop;
111926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
1120ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    if (!coin) {
1121ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark        return;
1122ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark    }
112326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
112426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* startPtT = coin->fCoinPtTStart;
112526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* oStartPtT = coin->fOppPtTStart;
112626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(startPtT->contains(oStartPtT));
112726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd));
112826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* start = startPtT->span();
112926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oStart = oStartPtT->span();
113026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* end = coin->fCoinPtTEnd->span();
113126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span();
113226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* test = start->upCast()->next();
113326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->upCast()->next();
113426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while (test != end || oTest != oEnd) {
113526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool bumpTest = true;
113626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            bool bumpOTest = true;
113726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!test->ptT()->contains(oTest->ptT())) {
113826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // use t ranges to guess which one is missing
113926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double startRange = coin->fCoinPtTEnd->fT - startPtT->fT;
114026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double startPart = (test->t() - startPtT->fT) / startRange;
114126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT;
114226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
114326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (startPart == oStartPart) {
114426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    // data is corrupt
114526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddCorruptCoin_Glitch, id, start, oStart);
114626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    break;
114726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
114826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (startPart < oStartPart) {
114926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    double newT = oStartPtT->fT + oStartRange * startPart;
115026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddExpandedCoin_Glitch, id, oStart, newT, test->pt());
115126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bumpOTest = false;
115226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                } else {
115326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    double newT = startPtT->fT + startRange * oStartPart;
115426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddExpandedCoin_Glitch, id, start, newT, oTest->pt());
115526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    bumpTest = false;
115626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
115726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
115826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (bumpTest && test != end) {
115926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                test = test->upCast()->next();
116026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
116126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (bumpOTest && oTest != oEnd) {
116226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next();
116326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
116426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
116526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((coin = coin->fNext));
116626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
116726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
116826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, double tEnd,
116926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs, double* coinTe) {
117026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double denom = overE->fT - overS->fT;
117126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double start = 0 < denom ? tStart : tEnd;
117226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double end = 0 < denom ? tEnd : tStart;
117326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double sRatio = (start - overS->fT) / denom;
117426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double eRatio = (end - overS->fT) / denom;
117526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio;
117626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio;
117726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
117826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
117926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s,
118026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpPtT* over1e) const {
118126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* check = this->fTop;
118226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    while (check) {
118326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (check->fCoinPtTStart->span() == over1s->span()
118426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                && check->fOppPtTStart->span() == outer->fOppPtTStart->span()) {
118526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(check->fCoinPtTEnd->span() == over1e->span()
118626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    || !fDebugState->debugRunFail());
118726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span()
118826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    || !fDebugState->debugRunFail());
118926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return false;
119026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
119126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span()
119226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                && check->fOppPtTStart->span() == over1s->span()) {
119326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(check->fCoinPtTEnd->span() == outer->fCoinPtTEnd->span()
119426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    || !fDebugState->debugRunFail());
119526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(check->fOppPtTEnd->span() == over1e->span()
119626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    || !fDebugState->debugRunFail());
119726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return false;
119826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
119926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        check = check->fNext;
120026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
120126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return true;
120226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
120326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
120426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
120526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                      const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd,
120626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
120726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const {
120826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    double coinTs, coinTe, oppTs, oppTe;
120926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe);
121026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe);
121126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* coinSeg = coinPtTStart->segment();
121226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* oppSeg = oppPtTStart->segment();
121326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(coinSeg != oppSeg);
121426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* check = this->fTop;
121526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    ;
121626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    while (check) {
121726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* checkCoinSeg = check->fCoinPtTStart->segment();
121826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* checkOppSeg;
121926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (checkCoinSeg != coinSeg && checkCoinSeg != oppSeg) {
122026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            goto next;
122126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
122226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        checkOppSeg = check->fOppPtTStart->segment();
122326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (checkOppSeg != coinSeg && checkOppSeg != oppSeg) {
122426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            goto next;
122526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
122626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        {
122726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            int cTs = coinTs;
122826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            int cTe = coinTe;
122926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            int oTs = oppTs;
123026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            int oTe = oppTe;
123126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (checkCoinSeg != coinSeg) {
123226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkASSERT(checkOppSeg != oppSeg);
123326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(cTs, oTs);
123426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                SkTSwap(cTe, oTe);
123526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
123626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            int tweenCount = (int) between(check->fCoinPtTStart->fT, cTs, check->fCoinPtTEnd->fT)
123726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                           + (int) between(check->fCoinPtTStart->fT, cTe, check->fCoinPtTEnd->fT)
123826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                           + (int) between(check->fOppPtTStart->fT, oTs, check->fOppPtTEnd->fT)
123926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                           + (int) between(check->fOppPtTStart->fT, oTe, check->fOppPtTEnd->fT);
124026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    //        SkASSERT(tweenCount == 0 || tweenCount == 4);
124126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (tweenCount) {
124226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return true;
124326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
124426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
124526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarknext:
124626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        check = check->fNext;
124726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
124826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) {
124926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(oppTs, oppTe);
125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (coinTs > coinTe) {
125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(coinTs, coinTe);
125326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkTSwap(oppTs, oppTe);
125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    bool cs = coinSeg->debugAddMissing(coinTs, oppSeg);
125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    bool ce = coinSeg->debugAddMissing(coinTe, oppSeg);
125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (cs == ce) {
125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return false;
125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return true;
126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const {
126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* outer = fHead;
126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!outer) {
126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing can modify the list that this is walking
127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // save head so that walker can iterate over old data unperturbed
127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // addifmissing adds to head freely then add saved head in the end
127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment();
127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(outerCoin == outer->fCoinPtTEnd->segment());
127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* outerOpp = outer->fOppPtTStart->segment();
127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkASSERT(outerOpp == outer->fOppPtTEnd->segment());
127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkCoincidentSpans* inner = outer;
127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        while ((inner = inner->fNext)) {
127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double overS, overE;
127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* innerCoin = inner->fCoinPtTStart->segment();
128026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(innerCoin == inner->fCoinPtTEnd->segment());
128126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSegment* innerOpp = inner->fOppPtTStart->segment();
128226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkASSERT(innerOpp == inner->fOppPtTEnd->segment());
128326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (outerCoin == innerCoin
128426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
128526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
128626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
128726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
128826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        outer->fOppPtTStart, outer->fOppPtTEnd,
128926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fOppPtTStart, inner->fOppPtTEnd)) {
129026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinPtTStart);
129126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
129226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } else if (outerCoin == innerOpp
129326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
129426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
129526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
129626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
129726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        outer->fOppPtTStart, outer->fOppPtTEnd,
129826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fCoinPtTStart, inner->fCoinPtTEnd)) {
129926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPtTStart);
130026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
130126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } else if (outerOpp == innerCoin
130226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
130326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
130426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
130526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
130626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        outer->fCoinPtTStart, outer->fCoinPtTEnd,
130726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fOppPtTStart, inner->fOppPtTEnd)) {
130826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinPtTStart);
130926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
131026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } else if (outerOpp == innerOpp
131126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
131226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
131326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
131426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
131526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        outer->fCoinPtTStart, outer->fCoinPtTEnd,
131626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        inner->fCoinPtTStart, inner->fCoinPtTEnd)) {
131726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPtTStart);
131826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
131926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            } else if (outerCoin != innerCoin) {
132026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                // check to see if outer span overlaps the inner span
132126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    // look for inner segment in pt-t list
132226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    // if present, and if t values are in coincident range
132326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    // add two pairs of new coincidence
132426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* testS = outer->fCoinPtTStart->debugContains(innerCoin);
132526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                const SkOpPtT* testE = outer->fCoinPtTEnd->debugContains(innerCoin);
132626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                if (testS && testS->fT >= inner->fCoinPtTStart->fT
132726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        && testE && testE->fT <= inner->fCoinPtTEnd->fT
132826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        && this->testForCoincidence(outer, testS, testE)) {
132926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (this->debugAddIfMissing(outer, testS, testE)) {
133026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        log->record(kAddMissingCoin_Glitch, id, outer, testS, testE);
133126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
133226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                } else {
133326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    testS = inner->fCoinPtTStart->debugContains(outerCoin);
133426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    testE = inner->fCoinPtTEnd->debugContains(outerCoin);
133526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    if (testS && testS->fT >= outer->fCoinPtTStart->fT
133626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            && testE && testE->fT <= outer->fCoinPtTEnd->fT
133726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            && this->testForCoincidence(inner, testS, testE)) {
133826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        if (this->debugAddIfMissing(inner, testS, testE)) {
133926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                            log->record(kAddMissingCoin_Glitch, id, inner, testS, testE);
134026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                        }
134126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                    }
134226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                }
134326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
134426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
134526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((outer = outer->fNext));
134626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
134726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
134826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const {
134926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
135026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
135126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return false;
135226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
135326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    bool expanded = false;
135426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
135526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpan* start = coin->fCoinPtTStart->span()->upCast();
135626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* end = coin->fCoinPtTEnd->span();
135726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* segment = coin->fCoinPtTStart->segment();
135826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* oppSegment = coin->fOppPtTStart->segment();
135926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpan* prev = start->prev();
136026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (prev && prev->debugContains(oppSegment)) {
136126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double midT = (prev->t() + start->t()) / 2;
136226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (segment->isClose(midT, oppSegment)) {
136326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kExpandCoin_Glitch, id, coin, prev);
136426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
136526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
136626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next();
136726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (next && next->debugContains(oppSegment)) {
136826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            double midT = (end->t() + next->t()) / 2;
136926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (segment->isClose(midT, oppSegment)) {
137026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kExpandCoin_Glitch, id, coin, next);
137126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
137226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
137326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((coin = coin->fNext));
137426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return expanded;
137526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
137626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
137726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugFixAligned(const char* id, SkPathOpsDebug::GlitchLog* log) const {
137826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
137926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
138026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
138126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
138226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
138326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fCoinPtTStart->deleted()) {
138426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTStart);
138526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
138626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fCoinPtTEnd->deleted()) {
138726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTEnd);
138826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
138926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fOppPtTStart->deleted()) {
139026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTStart);
139126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
139226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fOppPtTEnd->deleted()) {
139326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTEnd);
139426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
139526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((coin = coin->fNext));
139626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    coin = fHead;
139726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
139826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fCoinPtTStart->collapsed(coin->fCoinPtTEnd)) {
139926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kCollapsedCoin_Glitch, id, coin, coin->fCoinPtTStart);
140026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
140126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (coin->fOppPtTStart->collapsed(coin->fOppPtTEnd)) {
140226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            log->record(kCollapsedCoin_Glitch, id, coin, coin->fOppPtTStart);
140326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
140426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((coin = coin->fNext));
140526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
140626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
140726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const {
140826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkCoincidentSpans* coin = fHead;
140926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!coin) {
141026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return;
141126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
141226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
141326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* end = coin->fCoinPtTEnd->span();
141426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oldEnd = end;
141526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpan* start = coin->fCoinPtTStart->span()->debugStarter(&end);
141626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span();
141726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oOldEnd = oEnd;
141826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oStart = coin->fOppPtTStart->span()->debugStarter(&oEnd);
141926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        bool flipped = (end == oldEnd) != (oEnd == oOldEnd);
142026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (flipped) {
142126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkTSwap(oStart, oEnd);
142226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
142326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* next = start;
142426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* oNext = oStart;
142526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {
142626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            next = next->upCast()->next();
142726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            oNext = flipped ? oNext->prev() : oNext->upCast()->next();
142826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (next == end || oNext == oEnd) {
142926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                break;
143026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
143126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!next->containsCoinEnd(oNext)) {
143226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kMarkCoinEnd_Glitch, id, next, oNext);
143326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
143426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* nextSpan = next->upCast();
143526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            const SkOpSpan* oNextSpan = oNext->upCast();
143626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (!nextSpan->containsCoincidence(oNextSpan)) {
143726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                log->record(kMarkCoinInsert_Glitch, id, nextSpan, oNextSpan);
143826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
143926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while (true);
144026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((coin = coin->fNext));
144126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
144226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
144326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
1444624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const {
1445624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkCoincidentSpans* span = fHead;
1446624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    while (span) {
1447624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__,
1448624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark                span->fCoinPtTStart->segment()->debugID(),
1449624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark                span->fCoinPtTStart->fT, span->fCoinPtTEnd->fT);
1450624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__,
1451624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark                span->fOppPtTStart->segment()->debugID(),
1452624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark                span->fOppPtTStart->fT, span->fOppPtTEnd->fT);
1453624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        span = span->fNext;
1454624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
1455624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
1456624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
145726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE
145826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* log) const {
145926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = &fHead;
146026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
146126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        segment->debugCheckHealth(id, log);
146226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((segment = segment->next()));
146326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
146426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
146526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log,
146626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpCoincidence* coincidence) const {
146726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = &fHead;
146826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
146926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        segment->debugMissingCoincidence(id, log, coincidence);
147026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((segment = segment->next()));
147126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
147226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif
147326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
14744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const {
14754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE
147654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* span = &fHead;
147754359294a7c9dc54802d512a5d891a35c1663392caryclark    double lastT = -1;
147896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkOpSpanBase* prev = nullptr;
147954359294a7c9dc54802d512a5d891a35c1663392caryclark    int count = 0;
14804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int done = 0;
148154359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
148254359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!span->final()) {
148354359294a7c9dc54802d512a5d891a35c1663392caryclark            ++count;
148454359294a7c9dc54802d512a5d891a35c1663392caryclark            done += span->upCast()->done() ? 1 : 0;
148554359294a7c9dc54802d512a5d891a35c1663392caryclark        }
148654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(span->segment() == this);
148754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev->upCast()->next() == span);
148854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(!prev || prev == span->prev());
148954359294a7c9dc54802d512a5d891a35c1663392caryclark        prev = span;
149054359294a7c9dc54802d512a5d891a35c1663392caryclark        double t = span->ptT()->fT;
149154359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(lastT < t);
149254359294a7c9dc54802d512a5d891a35c1663392caryclark        lastT = t;
149354359294a7c9dc54802d512a5d891a35c1663392caryclark        span->debugValidate();
149454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (!span->final() && (span = span->upCast()->next()));
149554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(count == fCount);
149654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(done == fDoneCount);
149708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    SkASSERT(count >= fDoneCount);
149854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(span->final());
149954359294a7c9dc54802d512a5d891a35c1663392caryclark    span->debugValidate();
150054359294a7c9dc54802d512a5d891a35c1663392caryclark#endif
150154359294a7c9dc54802d512a5d891a35c1663392caryclark}
150254359294a7c9dc54802d512a5d891a35c1663392caryclark
150326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugAlignedEnd(double t, const SkPoint& pt) const {
150426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(zero_or_one(t));
150526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSegment* segment = this->segment();
150626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(t ? segment->lastPt() == pt : segment->pts()[0] == pt);
150726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (!debugAlignedInner()) {
150826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark          return false;
150926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
151026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if ((t ? segment->lastPt() : segment->pts()[0]) != pt) {
151126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        return false;
151226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
151326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = &this->fPtT;
151426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(t == ptT->fT);
151526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(pt == ptT->fPt);
151626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* test = ptT, * stopPtT = ptT;
151726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    while ((test = test->next()) != stopPtT) {
151826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSegment* other = test->segment();
151926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (other == this->segment()) {
152026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
152126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
152226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (!zero_or_one(test->fT)) {
152326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            continue;
152426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
152526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if ((test->fT ? other->lastPt() : other->pts()[0]) != pt) {
152626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return false;
152726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
152826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
152926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return this->fAligned;
153026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
153126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
153226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugAlignedInner() const {
153326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    // force the spans to share points and t values
153426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT;
153526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkPoint& pt = ptT->fPt;
153626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
153726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT->fPt != pt) {
153826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return false;
153926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
154026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpSpanBase* span = ptT->span();
154126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = ptT;
154226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        do {
154326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if ((test = test->next()) == stopPtT) {
154426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                break;
154526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
154626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (span == test->span() && !span->segment()->ptsDisjoint(*ptT, *test)) {
154726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return false;
154826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
154926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        } while (true);
155026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while ((ptT = ptT->next()) != stopPtT);
155126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return true;
155226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
155326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
155454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const {
155554359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
155654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* next = this;
155754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* nextCoin;
155854359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
155954359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoinEnd;
156054359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin);
156154359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
156254359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* checkCoin = this->fCoinEnd;
156354359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpanBase* innerCoin = checkCoin;
156454359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
156554359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoinEnd;
156654359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
156754359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident end loop ***\n");
156854359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
156954359294a7c9dc54802d512a5d891a35c1663392caryclark                }
157054359294a7c9dc54802d512a5d891a35c1663392caryclark            }
157154359294a7c9dc54802d512a5d891a35c1663392caryclark        }
157254359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
157354359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
157454359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
157554359294a7c9dc54802d512a5d891a35c1663392caryclark}
157654359294a7c9dc54802d512a5d891a35c1663392caryclark
157726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugContains(const SkOpSegment* segment) const {
157826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* start = &fPtT;
157926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* walk = start;
158026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    while ((walk = walk->next()) != start) {
158126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (walk->segment() == segment) {
158226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return true;
158326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
158426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
158526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return false;
158626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
158726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
158826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const {
158926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* end = *endPtr;
159026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() == end->segment());
159126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpSpanBase* result;
159226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    if (t() < end->t()) {
159326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = this;
159426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } else {
159526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        result = end;
159626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        *endPtr = this;
159726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    }
159826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    return result->upCast();
159926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
160026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
160154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const {
160254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
160354359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* ptT = &fPtT;
160454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(ptT->span() == this);
160554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
160654359294a7c9dc54802d512a5d891a35c1663392caryclark//        SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt));
160754359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT->debugValidate();
160854359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT = ptT->next();
160954359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (ptT != &fPtT);
161054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->debugCoinEndLoopCheck());
161154359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final()) {
161254359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(this->upCast()->debugCoinLoopCheck());
161354359294a7c9dc54802d512a5d891a35c1663392caryclark    }
161454359294a7c9dc54802d512a5d891a35c1663392caryclark    if (fFromAngle) {
161554359294a7c9dc54802d512a5d891a35c1663392caryclark        fFromAngle->debugValidate();
161654359294a7c9dc54802d512a5d891a35c1663392caryclark    }
161754359294a7c9dc54802d512a5d891a35c1663392caryclark    if (!this->final() && this->upCast()->toAngle()) {
161854359294a7c9dc54802d512a5d891a35c1663392caryclark        this->upCast()->toAngle()->debugValidate();
161954359294a7c9dc54802d512a5d891a35c1663392caryclark    }
16204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
162154359294a7c9dc54802d512a5d891a35c1663392caryclark}
162254359294a7c9dc54802d512a5d891a35c1663392caryclark
162354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const {
162454359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
162554359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* next = this;
162654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* nextCoin;
162754359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
162854359294a7c9dc54802d512a5d891a35c1663392caryclark        nextCoin = next->fCoincident;
162954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin);
163054359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
163154359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* checkCoin = this->fCoincident;
163254359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpSpan* innerCoin = checkCoin;
163354359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
163454359294a7c9dc54802d512a5d891a35c1663392caryclark                innerCoin = innerCoin->fCoincident;
163554359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkCoin == innerCoin) {
163654359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkDebugf("*** bad coincident loop ***\n");
163754359294a7c9dc54802d512a5d891a35c1663392caryclark                    return false;
163854359294a7c9dc54802d512a5d891a35c1663392caryclark                }
163954359294a7c9dc54802d512a5d891a35c1663392caryclark            }
164054359294a7c9dc54802d512a5d891a35c1663392caryclark        }
164154359294a7c9dc54802d512a5d891a35c1663392caryclark        ++loop;
164254359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = nextCoin) && next != this);
164354359294a7c9dc54802d512a5d891a35c1663392caryclark    return true;
164454359294a7c9dc54802d512a5d891a35c1663392caryclark}
164554359294a7c9dc54802d512a5d891a35c1663392caryclark
1646624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code
1647624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const {
1648624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    if (!fIsCoincident[0]) {
1649624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        SkASSERT(!fIsCoincident[1]);
1650624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        return 0;
1651624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
1652624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    int count = 0;
1653624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkDEBUGCODE(int count2 = 0;)
1654624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    for (int index = 0; index < fUsed; ++index) {
1655624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[0] & (1 << index)) {
1656624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count;
1657624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1658624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG
1659624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        if (fIsCoincident[1] & (1 << index)) {
1660624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark            ++count2;
1661624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        }
1662624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif
1663624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
1664624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkASSERT(count == count2);
1665624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    return count;
1666624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
1667624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
166854359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h"
166954359294a7c9dc54802d512a5d891a35c1663392caryclark
167026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const {
167126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this != check);
167226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
167326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
167426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
167526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
167626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT == check) {
167726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return true;
167826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
167926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
168026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
168126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
168226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
168326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return false;
168426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
168526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
168626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
168726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
168926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
169026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const {
169126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    SkASSERT(this->segment() != check);
169226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    const SkOpPtT* ptT = this;
169326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    int links = 0;
169426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    do {
169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ptT = ptT->next();
169626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (ptT->segment() == check) {
169726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return ptT;
169826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
169926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        ++links;
170026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        const SkOpPtT* test = this;
170126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        for (int index = 0; index < links; ++index) {
170226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            if (ptT == test) {
170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark                return nullptr;
170426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            }
170526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            test = test->next();
170626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
170726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark    } while (true);
170826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}
170926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark
171054359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const {
171154359294a7c9dc54802d512a5d891a35c1663392caryclark    int loop = 0;
171254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* next = this;
171354359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
171454359294a7c9dc54802d512a5d891a35c1663392caryclark        for (int check = 1; check < loop - 1; ++check) {
171554359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* checkPtT = this->fNext;
171654359294a7c9dc54802d512a5d891a35c1663392caryclark            const SkOpPtT* innerPtT = checkPtT;
171754359294a7c9dc54802d512a5d891a35c1663392caryclark            for (int inner = check + 1; inner < loop; ++inner) {
171854359294a7c9dc54802d512a5d891a35c1663392caryclark                innerPtT = innerPtT->fNext;
171954359294a7c9dc54802d512a5d891a35c1663392caryclark                if (checkPtT == innerPtT) {
172054359294a7c9dc54802d512a5d891a35c1663392caryclark                    if (report) {
172154359294a7c9dc54802d512a5d891a35c1663392caryclark                        SkDebugf("*** bad ptT loop ***\n");
172254359294a7c9dc54802d512a5d891a35c1663392caryclark                    }
172354359294a7c9dc54802d512a5d891a35c1663392caryclark                    return loop;
172454359294a7c9dc54802d512a5d891a35c1663392caryclark                }
17254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
17264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
172726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // there's nothing wrong with extremely large loop counts -- but this may appear to hang
172826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // by taking a very long time to figure out that no loop entry is a duplicate
172926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        // -- and it's likely that a large loop count is indicative of a bug somewhere
173026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        if (++loop > 1000) {
173126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            SkDebugf("*** loop count exceeds 1000 ***\n");
173226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark            return 1000;
173326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark        }
173454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = next->fNext) && next != this);
173554359294a7c9dc54802d512a5d891a35c1663392caryclark    return 0;
173654359294a7c9dc54802d512a5d891a35c1663392caryclark}
173754359294a7c9dc54802d512a5d891a35c1663392caryclark
173854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const {
173954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE
17404e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark    SkOpGlobalState::Phase phase = contour()->globalState()->phase();
17414e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark    if (phase == SkOpGlobalState::kIntersecting
17424e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark            || phase == SkOpGlobalState::kFixWinding) {
174354359294a7c9dc54802d512a5d891a35c1663392caryclark        return;
17444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
174554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext);
174654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext != this);
174754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(fNext->fNext);
174854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(debugLoopLimit(false) == 0);
17494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
17504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org}
17511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
17521049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) {
17531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (num == (int) num) {
17541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%d", (int) num);
17551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    } else {
17561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkString str;
17571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.printf("%1.9g", num);
17581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        int width = (int) str.size();
17591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const char* cStr = str.c_str();
17601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        while (cStr[width - 1] == '0') {
17611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            --width;
17621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
17631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        str.resize(width);
17641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("%sf", str.c_str());
17651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
17661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
17671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
17681049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) {
17691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    for (int index = 0; index < count; ++index) {
17701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fX);
17711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf(", ");
17721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        output_scalar(pts[index].fY);
17731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        if (index + 1 < count) {
17741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf(", ");
17751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
17761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
17771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
17781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
17791049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) {
17801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    uint8_t verb;
17811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPoint pts[4];
17821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
17831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        switch (verb) {
17841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kMove_Verb:
17851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.moveTo(", pathName);
17861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[0], 1);
17871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
17881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                continue;
17891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kLine_Verb:
17901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.lineTo(", pathName);
17911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 1);
17921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
17931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
17941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kQuad_Verb:
17951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.quadTo(", pathName);
17961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
17971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
17981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
17991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kConic_Verb:
18001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.conicTo(", pathName);
18011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 2);
18021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(", %1.9gf);\n", iter.conicWeight());
18031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
18041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kCubic_Verb:
18051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.cubicTo(", pathName);
18061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                output_points(&pts[1], 3);
18071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf(");\n");
18081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
18091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            case SkPath::kClose_Verb:
18101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDebugf("    %s.close();\n", pathName);
18111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                break;
18121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            default:
18131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                SkDEBUGFAIL("bad verb");
18141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                return;
18151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
18161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
18171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
18181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
18191049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = {
18201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kWinding_FillType",
18211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kEvenOdd_FillType",
18221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseWinding_FillType",
18231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    "kInverseEvenOdd_FillType"
18241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
18251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
18261049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) {
18271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::RawIter iter(path);
18281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0
18291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION
183096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0;
18311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (rectCount > 0) {
18321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkRect> rects;
18331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkTDArray<SkPath::Direction> directions;
18341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        rects.setCount(rectCount);
18351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        directions.setCount(rectCount);
18361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        path.rectContours(rects.begin(), directions.begin());
18371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        for (int contour = 0; contour < rectCount; ++contour) {
18381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            const SkRect& rect = rects[contour];
18391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
18401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
18411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
18421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
18431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        return;
18441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
18451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif
18461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkPath::FillType fillType = path.getFillType();
18471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType);
18481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (includeDeclaration) {
18491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("    SkPath %s;\n", name);
18501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
18511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("    %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]);
18521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    iter.setPath(path);
18531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    showPathContours(iter, name);
18541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
1855