SkPathOpsDebug.cpp revision a35ab3e6e024d0b548ded26a2e3b8ecd838ead93
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 1530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_IF 1630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_IF(cond, coin) \ 17ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false) 1830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 1930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_WITH_NULL_IF 2030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_WITH_NULL_IF(cond, span) \ 21ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, span); } while (false) 2230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef RETURN_FALSE_IF 2430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define RETURN_FALSE_IF(cond, span) \ 25ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kReturnFalse_Glitch, span); \ 26ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (false) 2730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2855888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans; 2926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 3054359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 3154359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail; 3254359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 34624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 35624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 36624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 37624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 38624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 39624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 40624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 41624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 42624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 45570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 468cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 47fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 48fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 49570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5054359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 5154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 5354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 6126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 62ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 64ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumChangedDict; 65ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumVisitedDict; 66ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 67ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic const int kGlitchType_Count = SkPathOpsDebug::kUnalignedTail_Glitch + 1; 6826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 6926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 7355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* fOppSegment; 7426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 7526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 7626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 7855888e44171ffd48b591d19256884a969fe4da17caryclark double fStartT; 7955888e44171ffd48b591d19256884a969fe4da17caryclark double fEndT; 8055888e44171ffd48b591d19256884a969fe4da17caryclark double fOppStartT; 8155888e44171ffd48b591d19256884a969fe4da17caryclark double fOppEndT; 8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 83ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchType fType; 84ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 85ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void dumpType() const; 8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 8826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 89ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void init(const SkOpGlobalState* state) { 90ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fGlobalState = state; 91ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 92ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 93ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* recordCommon(GlitchType type) { 9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 9855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = nullptr; 9926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 10026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 10126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 10355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = SK_ScalarNaN; 10455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = SK_ScalarNaN; 10555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = SK_ScalarNaN; 10655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = SK_ScalarNaN; 10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 112ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 11326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 114ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 119ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 12055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 121ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 12255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 12355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = ptT; 12455888e44171ffd48b591d19256884a969fe4da17caryclark } 12555888e44171ffd48b591d19256884a969fe4da17caryclark 126ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 12755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* opp = NULL) { 128ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 12955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 13055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 13155888e44171ffd48b591d19256884a969fe4da17caryclark if (opp) { 13255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = opp->coinPtTStart(); 13355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = opp->coinPtTEnd(); 13455888e44171ffd48b591d19256884a969fe4da17caryclark } 13526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 13626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 137ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 13826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 139ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 14026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 14255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 146ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, double t, 14726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 148ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 15055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 15126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 154ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 15526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 156ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 15755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 15855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 15926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 16055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = coinSpan; 16155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = endSpan; 16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 164ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 16555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* base) { 166ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 16755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 16855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 16955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 17026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 172ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 17326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 174ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 17526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 17626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 181ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, double startT, 18255888e44171ffd48b591d19256884a969fe4da17caryclark double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 183ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 18455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 18555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = startT; 18655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = endT; 18755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = oppSeg; 18855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = oppStartT; 18955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = oppEndT; 19055888e44171ffd48b591d19256884a969fe4da17caryclark } 19155888e44171ffd48b591d19256884a969fe4da17caryclark 192ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, 19355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span) { 194ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 19555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 19655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 19755888e44171ffd48b591d19256884a969fe4da17caryclark } 19855888e44171ffd48b591d19256884a969fe4da17caryclark 199ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, double t, const SkOpSpanBase* span) { 200ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 20155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 20255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 20355888e44171ffd48b591d19256884a969fe4da17caryclark } 20455888e44171ffd48b591d19256884a969fe4da17caryclark 205ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg) { 206ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 20755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 20855888e44171ffd48b591d19256884a969fe4da17caryclark } 20955888e44171ffd48b591d19256884a969fe4da17caryclark 210ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 21155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 212ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 21355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 21455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = ptT; 21555888e44171ffd48b591d19256884a969fe4da17caryclark } 21655888e44171ffd48b591d19256884a969fe4da17caryclark 21726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 218ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpGlobalState* fGlobalState; 21926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 220ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 221ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 222ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const SkPathOpsDebug::CoinDict& dict) { 223ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = dict.fDict.count(); 224ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 225ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->add(dict.fDict[index]); 226ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 227ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 228ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 229ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const CoinDictEntry& key) { 230ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = fDict.count(); 231ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 232ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark CoinDictEntry* entry = &fDict[index]; 233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fIteration == key.fIteration && entry->fLineNumber == key.fLineNumber) { 234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(!strcmp(entry->fFunctionName, key.fFunctionName)); 235ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fGlitchType == kUninitialized_Glitch) { 236ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = key.fGlitchType; 237ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 238ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 239ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 241ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *fDict.append() = key; 242ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 243ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 244ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 245ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 246ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 247ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void missing_coincidence(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 248ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 249ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // bool result = false; 250ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 251ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark /* result |= */ contour->debugMissingCoincidence(glitches); 252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 253ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 254ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 256ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_multiples(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 257ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (contour->debugMoveMultiples(glitches), false) { 260ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 261ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 262ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 263ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 264ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 265ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 266ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_nearby(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 269ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMoveNearby(glitches); 270ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 271ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 272ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToCoinChangedDict() { 278ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 279ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 280e6522ea38fa3bcfdf2d718ea5ad898b3b3d46e00caryclark SkPathOpsDebug::CheckHealth(fContourHead); 281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // see if next coincident operation makes a change; if so, record it 283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog glitches; 284ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const char* funcName = fCoinDictEntry.fFunctionName; 285ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!strcmp("calc_angles", funcName)) { 286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("missing_coincidence", funcName)) { 288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark missing_coincidence(&glitches, fContourHead); 289ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_multiples", funcName)) { 290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_multiples(&glitches, fContourHead); 291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_nearby", funcName)) { 292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_nearby(&glitches, fContourHead); 293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addExpanded", funcName)) { 294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddExpanded(&glitches); 295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addMissing", funcName)) { 296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 297ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddMissing(&glitches, &added); 298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addEndMovedSpans", funcName)) { 299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddEndMovedSpans(&glitches); 300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("correctEnds", funcName)) { 301ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugCorrectEnds(&glitches); 302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("expand", funcName)) { 303ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugExpand(&glitches); 304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("findOverlaps", funcName)) { 305ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("mark", funcName)) { 307ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugMark(&glitches); 308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("apply", funcName)) { 309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(0); // add missing case 312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (glitches.fGlitches.count()) { 314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinDictEntry.fGlitchType = glitches.fGlitches[0].fType; 315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinChangedDict.add(fCoinDictEntry); 317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 31855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 31926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 32055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 32155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 32255888e44171ffd48b591d19256884a969fe4da17caryclark SkOpContour* contour = contourList; 32355888e44171ffd48b591d19256884a969fe4da17caryclark do { 32455888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugShowActiveSpans(); 32555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((contour = contour->next())); 32655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 32755888e44171ffd48b591d19256884a969fe4da17caryclark} 32855888e44171ffd48b591d19256884a969fe4da17caryclark 329ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE || DEBUG_COIN 330ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList) { 33155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 33255888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(true); 333ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 334ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 33526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 33626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 33726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 338ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugCheckValid(&glitches); // don't call validate; spans may be inconsistent 33926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 340ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugCheckHealth(&glitches); 341ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMissingCoincidence(&glitches); 34226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 34381a478ca6c36aac3e53ce0373a281ac8940f4780caryclark bool added; 344ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddMissing(&glitches, &added); 345ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugExpand(&glitches); 346ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddExpanded(&glitches); 347ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugMark(&glitches); 34826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 34926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 35026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 35126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 35226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 35326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 35655888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 35755888e44171ffd48b591d19256884a969fe4da17caryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 35855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%02d: ", index); 35955888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fBase) { 3608016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(), 3618016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fBase->debugID()); 36255888e44171ffd48b591d19256884a969fe4da17caryclark } 36355888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSuspect) { 3648016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(), 3658016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fSuspect->debugID()); 36655888e44171ffd48b591d19256884a969fe4da17caryclark } 36755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSegment) { 36855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fSegment->debugID()); 36955888e44171ffd48b591d19256884a969fe4da17caryclark } 37055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fCoinSpan) { 3718016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(), 3728016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID()); 37355888e44171ffd48b591d19256884a969fe4da17caryclark } 37455888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fEndSpan) { 37555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 37655888e44171ffd48b591d19256884a969fe4da17caryclark } 37755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSpan) { 3788016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(), 3798016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID()); 38055888e44171ffd48b591d19256884a969fe4da17caryclark } 38155888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppEndSpan) { 38255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 38355888e44171ffd48b591d19256884a969fe4da17caryclark } 38455888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fStartT)) { 38555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" startT=%g", glitch.fStartT); 38655888e44171ffd48b591d19256884a969fe4da17caryclark } 38755888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fEndT)) { 38855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endT=%g", glitch.fEndT); 38955888e44171ffd48b591d19256884a969fe4da17caryclark } 39055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSegment) { 39155888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 39255888e44171ffd48b591d19256884a969fe4da17caryclark } 39355888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppStartT)) { 39455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppStartT=%g", glitch.fOppStartT); 39555888e44171ffd48b591d19256884a969fe4da17caryclark } 39655888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppEndT)) { 39755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndT=%g", glitch.fOppEndT); 39855888e44171ffd48b591d19256884a969fe4da17caryclark } 39955888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 40055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 40155888e44171ffd48b591d19256884a969fe4da17caryclark } 402ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DumpGlitchType(glitch.fType); 40355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("\n"); 40455888e44171ffd48b591d19256884a969fe4da17caryclark } 405ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 40655888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(false); 407ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 4086c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if 01 && DEBUG_ACTIVE_SPANS 409ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// SkDebugf("active after %s:\n", id); 41055888e44171ffd48b591d19256884a969fe4da17caryclark ShowActiveSpans(contourList); 41155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 41255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 41326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 41426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 4154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::DumpGlitchType(GlitchType glitchType) { 418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark switch (glitchType) { 419ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 420ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break; 423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 424ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 426ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 428ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 430ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 431ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 432ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCorrectEnd_Glitch: SkDebugf(" CorrectEnd"); break; 433ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 434ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 435ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kFail_Glitch: SkDebugf(" Fail"); break; 436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 439ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 440ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; 441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 443ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 444ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 446ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 447ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 448ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 449ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 450ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 451ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 452ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReturnFalse_Glitch: SkDebugf(" ReturnFalse"); break; 453ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 454ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 455ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 456ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUninitialized_Glitch: break; 457ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark default: SkASSERT(0); 458ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 459ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 461ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 46226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 463570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 46407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 46507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 46607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 46707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 46807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 46907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 47007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 47107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 47207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 47307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 47407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 47507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 47607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 47707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 47807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 47907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 480570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 48107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 48207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 48307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 484570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 48507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 48607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 48707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 48807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 48907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 49007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 49154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 49254359294a7c9dc54802d512a5d891a35c1663392caryclark 493a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 49407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 495385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 496cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 497385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 498a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 499570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 50007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 50107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 50207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 50307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 50407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 50507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 50607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 50707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 50807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 50907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 51007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 51107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 51207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 513a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 514a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 515570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5161049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 5171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 5181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 5191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 5201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 5211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5231049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 5241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 5251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 5261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 52755888e44171ffd48b591d19256884a969fe4da17caryclark "kXOR_PathOp", 5281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 5291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 5301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 53103b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 53203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 53303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 53403b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 5351049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 5361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 5371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 5381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 540086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex); 5411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5421049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 5431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 5441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 5451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 5461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 5471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 5481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 5494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 55127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 55226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 55326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 55426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 555ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 556ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 557ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSK_DECLARE_STATIC_MUTEX(gCoinDictMutex); 558ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 559ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToGlobalCoinDicts() { 560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkAutoMutexAcquire ac(&gCoinDictMutex); 561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict); 562ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict); 563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 56726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 56826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 56926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 57026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 57126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 57526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 57626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 57726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 57826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 57926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 58026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 58126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 58426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 58526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 58626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 59626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 59726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 59826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 59926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 60026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 60126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 60326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 60526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 60626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 60826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 64927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 65027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG 65127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const { 65227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE 65327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return FLAGS_runFail; 65427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else 65527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 65627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 65727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 65827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 65927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this is const so it can be called by const methods that overwise don't alter state 661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE || DEBUG_COIN 662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const { 663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark auto writable = const_cast<SkOpGlobalState*>(this); 664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->setPhase(phase); 666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::CoinDictEntry* entry = &writable->fCoinDictEntry; 669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fPreviousFuncName = entry->fFunctionName; 670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fIteration = iteration; 671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fLineNumber = lineNo; 672ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = SkPathOpsDebug::kUninitialized_Glitch; 673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fFunctionName = funcName; 674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fCoinVisitedDict.add(*entry); 675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->debugAddToCoinChangedDict(); 676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 679ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 68026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 68226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 68326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 68426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 68526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 68626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 68726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 68826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 69126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 69226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 69326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 694a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark#include "SkPathOpsConic.h" 695624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 696624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 697624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 698624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 699624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 700624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 701624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 702624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 703624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 704624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 705624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 706624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 707624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 708624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 709a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDQuad::debugSet(const SkDPoint* pts) { 710a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 711a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 712a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 713a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 714a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDCubic::debugSet(const SkDPoint* pts) { 715a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 716a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 717a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 718a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 719a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDConic::debugSet(const SkDPoint* pts, SkScalar weight) { 720a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fPts.debugSet(pts); 721a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fWeight = weight; 722a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 723a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 724ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 725ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 726ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 727ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 7284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 729570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 730570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 731ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 73255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT() 733ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* SkOpSegment::debugAddT(double t, SkPathOpsDebug::GlitchLog* log) const { 73455888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 73555888e44171ffd48b591d19256884a969fe4da17caryclark SkPoint pt = this->ptAtT(t); 73655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* span = &fHead; 73726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 73855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* result = span->ptT(); 73929b2563afb1677515739f1d24fb27733626eca92caryclark if (t == result->fT || this->match(result, this, t, pt)) { 74055888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 741ef4f32ac858825dc443cfe4739ea878fb0bf550fcaryclark return result; 74255888e44171ffd48b591d19256884a969fe4da17caryclark } 74355888e44171ffd48b591d19256884a969fe4da17caryclark if (t < result->fT) { 74455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = result->span()->prev(); 74530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(!prev, span); 74629b2563afb1677515739f1d24fb27733626eca92caryclark // marks in global state that new op span has been allocated 74729b2563afb1677515739f1d24fb27733626eca92caryclark this->globalState()->setAllocatedOpSpan(); 74855888e44171ffd48b591d19256884a969fe4da17caryclark// span->init(this, prev, t, pt); 74955888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 75055888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 75155888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 75255888e44171ffd48b591d19256884a969fe4da17caryclark// span->segment()->debugID(), span->debugID()); 75355888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 75455888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 75555888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 75655888e44171ffd48b591d19256884a969fe4da17caryclark } 75730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(span != &fTail, span); 75855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->upCast()->next())); 75955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 76029b2563afb1677515739f1d24fb27733626eca92caryclark return nullptr; // we never get here, but need this to satisfy compiler 76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 76226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 76326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 76426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 76826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 77055888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 77126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 77855888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 78426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 785ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 787ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugCheckHealth(SkPathOpsDebug::GlitchLog* glitches) const { 788ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveMultiples(glitches); 789ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveNearby(glitches); 790ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMissingCoincidence(glitches); 79155888e44171ffd48b591d19256884a969fe4da17caryclark} 79226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 79355888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll() 794ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const { 79555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span = &fHead; 79655888e44171ffd48b591d19256884a969fe4da17caryclark do { 797ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugClearOne(span, glitches); 79855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->next()->upCastable())); 799ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->globalState()->coincidence()->debugRelease(glitches, this); 80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 80126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 80255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne() 803ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const { 804ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->windValue()) glitches->record(SkPathOpsDebug::kCollapsedWindValue_Glitch, span); 805ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->oppValue()) glitches->record(SkPathOpsDebug::kCollapsedOppValue_Glitch, span); 806ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span->done()) glitches->record(SkPathOpsDebug::kCollapsedDone_Glitch, span); 80726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 80826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 80926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 81054359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 81196fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 81254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 81354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 81454359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 815dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 81654359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 817dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 81854359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 819dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 820dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 821dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 822dac1d17027dcaa5596885a9f333979418b35001ccaryclark 823ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 82455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited 82555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 82655888e44171ffd48b591d19256884a969fe4da17caryclark // reset visited flag back to false 82755888e44171ffd48b591d19256884a969fe4da17caryclark do { 82855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 82955888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != stopPtT) { 83055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->segment(); 83155888e44171ffd48b591d19256884a969fe4da17caryclark opp->resetDebugVisited(); 83255888e44171ffd48b591d19256884a969fe4da17caryclark } 83355888e44171ffd48b591d19256884a969fe4da17caryclark } while (!span->final() && (span = span->upCast()->next())); 83455888e44171ffd48b591d19256884a969fe4da17caryclark} 83555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 83655888e44171ffd48b591d19256884a969fe4da17caryclark 837ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 83855888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence() 83955888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves 84055888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear 84155888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed 84255888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given 84355888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C: 84455888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 84555888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C. 84655888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2, 84755888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B. 848ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 84926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 85026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 85126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 85326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 85455888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 85526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 85626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 85726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 85826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 85926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 86026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->span()->segment(); 86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 86755888e44171ffd48b591d19256884a969fe4da17caryclark if (!opp->debugVisited()) { 86826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87355888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this) { 87455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 87555888e44171ffd48b591d19256884a969fe4da17caryclark } 87626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 87955888e44171ffd48b591d19256884a969fe4da17caryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88255888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88455888e44171ffd48b591d19256884a969fe4da17caryclark } 88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 88726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 88826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 88926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 89326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 895ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = priorPtT->span()->segment(); 89626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 89826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90755888e44171ffd48b591d19256884a969fe4da17caryclark if (priorPtT == ptT) { 90855888e44171ffd48b591d19256884a969fe4da17caryclark continue; 90955888e44171ffd48b591d19256884a969fe4da17caryclark } 91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 91626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 91855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 91955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPtT = ptT->span()->ptT(); 92055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 92155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 92255888e44171ffd48b591d19256884a969fe4da17caryclark if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 92326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 92426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 92555888e44171ffd48b591d19256884a969fe4da17caryclark if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 92655888e44171ffd48b591d19256884a969fe4da17caryclark // mark coincidence 92730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE 92855888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 92955888e44171ffd48b591d19256884a969fe4da17caryclark// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 93055888e44171ffd48b591d19256884a969fe4da17caryclark// rootOppEnd->debugID()); 93155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 932ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMissingCoin_Glitch, priorPtT, ptT, oppStart, oppEnd); 93355888e44171ffd48b591d19256884a969fe4da17caryclark // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 93455888e44171ffd48b591d19256884a969fe4da17caryclark // } 93555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 936d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 93755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 93855888e44171ffd48b591d19256884a969fe4da17caryclark // result = true; 93926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 94026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 94126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 94226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 94326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 94426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 94526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 94655888e44171ffd48b591d19256884a969fe4da17caryclark DebugClearVisited(&fHead); 94755888e44171ffd48b591d19256884a969fe4da17caryclark return; 94826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 94926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 95055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples() 95155888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed 952ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const { 95355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 95426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 95526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 95626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 95726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(addCount >= 1); 95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (addCount == 1) { 95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 96026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 96526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 96626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 96726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 97126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 97226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 100326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 100526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 100626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 100826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 100926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 101026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 101126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 101326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 101426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 101526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 101626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 101726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 101826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 101926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 102026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 102226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 102326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 102426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 102526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 102726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 102826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 102955888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 1030ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugMergeMatches(glitches, oppSpan); 1031ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugAddOpp(glitches, oppSpan); 103255888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 103326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 103426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 103555888e44171ffd48b591d19256884a969fe4da17caryclark tryNextSpan: 103626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 103726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 103826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 103955888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan: 104026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 104126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 104255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 104355888e44171ffd48b591d19256884a969fe4da17caryclark return; 104426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 104526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 104655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby() 104755888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1048ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const { 104955888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 105055888e44171ffd48b591d19256884a969fe4da17caryclark // release undeleted spans pointing to this seg that are linked to the primary span 105155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* spanBase = &fHead; 105226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 105355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = spanBase->ptT(); 105455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* headPtT = ptT; 105555888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != headPtT) { 105655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = ptT->span(); 105755888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this && !ptT->deleted() && test != spanBase 105855888e44171ffd48b591d19256884a969fe4da17caryclark && test->ptT() == ptT) { 105955888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 106055888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase == &fHead) { 1061ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll_Glitch, this); 106255888e44171ffd48b591d19256884a969fe4da17caryclark// return; 106355888e44171ffd48b591d19256884a969fe4da17caryclark } 1064ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyReleaseFinal_Glitch, spanBase, ptT); 106555888e44171ffd48b591d19256884a969fe4da17caryclark } else if (test->prev()) { 1066ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyRelease_Glitch, test, headPtT); 106755888e44171ffd48b591d19256884a969fe4da17caryclark } 106855888e44171ffd48b591d19256884a969fe4da17caryclark// break; 106926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 107026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 107155888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = spanBase->upCast()->next(); 107255888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 107355888e44171ffd48b591d19256884a969fe4da17caryclark 107455888e44171ffd48b591d19256884a969fe4da17caryclark // This loop looks for adjacent spans which are near by 107555888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = &fHead; 107655888e44171ffd48b591d19256884a969fe4da17caryclark do { // iterate through all spans associated with start 107755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = spanBase->upCast()->next(); 107855888e44171ffd48b591d19256884a969fe4da17caryclark if (this->spansNearby(spanBase, test)) { 107955888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 108055888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->prev()) { 1081ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 108255888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1083ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll2_Glitch, this); 108455888e44171ffd48b591d19256884a969fe4da17caryclark // return 108555888e44171ffd48b591d19256884a969fe4da17caryclark } 108655888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1087ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMerge_Glitch, spanBase); 108855888e44171ffd48b591d19256884a969fe4da17caryclark } 108955888e44171ffd48b591d19256884a969fe4da17caryclark } 109055888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = test; 109155888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 109255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 109326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 109426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 109526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 10964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 10971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1100025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 1101025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const { 1102025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { 1103025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = index; 1104025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = SkTMin(t, fDebugBaseMin); 1105025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = SkTMax(t, fDebugBaseMax); 1106025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1107025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1108025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); 1109025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugLastMax < 0 || fDebugLastIndex == index) { 1110025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = index; 1111025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = SkTMin(t, fDebugLastMin); 1112025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = SkTMax(t, fDebugLastMax); 1113025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1114025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1115025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); 1116025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); 1117025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 1118025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 1119025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 112054359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 11214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const { 11224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 11234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 11244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 11254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 11274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 112854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 112954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 113054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 11314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 11344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 113754359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 11381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); 113955888e44171ffd48b591d19256884a969fe4da17caryclark // since endpoints may have be adjusted, show actual computed curves 114055888e44171ffd48b591d19256884a969fe4da17caryclark SkDCurve curvePart; 114155888e44171ffd48b591d19256884a969fe4da17caryclark this->subDivide(span, span->next(), &curvePart); 114255888e44171ffd48b591d19256884a969fe4da17caryclark const SkDPoint* pts = curvePart.fCubic.fPts; 114355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 11444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 114555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 11464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 114855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9gf", curvePart.fConic.fWeight); 11491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 115055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 115154359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 1152624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=?"); 11534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1154624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=%d", span->windSum()); 1155624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1156624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 1157624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=?"); 1158624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1159624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=%d", span->oppSum()); 1160624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1161624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windValue=%d", span->windValue()); 1162624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 1163624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppValue=%d", span->oppValue()); 11644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 116554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 116654359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 11674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 11694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 117054359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 117154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 117254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 11731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 11744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 11754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 11764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 11774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 117854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 117954359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 118054359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 11814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 11824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 118354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 11844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 118554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 118654359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 118754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 118854359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 118954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 119054359294a7c9dc54802d512a5d891a35c1663392caryclark } 119154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 11924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 119454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 11954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 119654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 11971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 11984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 11994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 12004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 12014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 120254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 120354359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 120454359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 120554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 120654359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 120754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 120854359294a7c9dc54802d512a5d891a35c1663392caryclark } 120954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 121054359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 121154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 121254359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 121354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 121454359294a7c9dc54802d512a5d891a35c1663392caryclark } 121554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 121654359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 12174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 121954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 12204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 12214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 122254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 12234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 122554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 12264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 122754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 12284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 122954359294a7c9dc54802d512a5d891a35c1663392caryclark 12304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 12314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 123226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 123326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 123426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 123555888e44171ffd48b591d19256884a969fe4da17caryclark This checks the distance between start points; the distance between 123626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 123726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 123826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 123926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 124026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 124126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 124226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 124326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 124426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 124526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 124626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 124726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 124826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 124926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 125326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 127355888e44171ffd48b591d19256884a969fe4da17caryclark } while (test->fNext != this); 127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 127754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 127854359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 127954359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 128054359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 128154359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 1282eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fPart.fCurve), 128354359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 128454359294a7c9dc54802d512a5d891a35c1663392caryclark break; 128554359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 1286eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fPart.fCurve), 128754359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 128854359294a7c9dc54802d512a5d891a35c1663392caryclark break; 12891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 12901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 1291eed356d281adbf93ecbd89cb23913a7861cd8578caryclark CONIC_DEBUG_DATA(fPart.fCurve, fPart.fCurve.fConic.fWeight), 12921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 12931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 129454359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 1295eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fPart.fCurve), 129654359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 129754359294a7c9dc54802d512a5d891a35c1663392caryclark break; 129854359294a7c9dc54802d512a5d891a35c1663392caryclark default: 129954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 13001b24933e52f50773de29332387a12721811f3012mtklein } 130154359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 130254359294a7c9dc54802d512a5d891a35c1663392caryclark} 130354359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 130454359294a7c9dc54802d512a5d891a35c1663392caryclark 1305624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 130654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 130754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 130854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 130954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 131054359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 131154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 131254359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 131354359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 131454359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 131554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 131654359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 131754359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 131854359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 132254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 132355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 132455888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 132555888e44171ffd48b591d19256884a969fe4da17caryclark return; 132655888e44171ffd48b591d19256884a969fe4da17caryclark } 132755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 132854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 132954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 133054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 133154359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 133254359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 133354359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 133454359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 133554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 133654359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 133754359294a7c9dc54802d512a5d891a35c1663392caryclark return; 133854359294a7c9dc54802d512a5d891a35c1663392caryclark } 133954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 134054359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 134154359294a7c9dc54802d512a5d891a35c1663392caryclark return; 134254359294a7c9dc54802d512a5d891a35c1663392caryclark } 134354359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 134454359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 134554359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 134654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 134754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 134854359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 134954359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 135054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 135154359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1352624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 135354359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 135454359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 135554359294a7c9dc54802d512a5d891a35c1663392caryclark } 135654359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 135754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 135854359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1359624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 136054359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 136154359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 136254359294a7c9dc54802d512a5d891a35c1663392caryclark } 136354359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 136454359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1365182b499cd75c971f85cdf52c1827b3c220cc9011caryclark SkASSERT(wind == 0 || !FLAGS_runFail); 136654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(opp == 0 || !FLAGS_runFail); 136754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 136854359294a7c9dc54802d512a5d891a35c1663392caryclark} 136954359294a7c9dc54802d512a5d891a35c1663392caryclark 137054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 137154359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 137254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 137354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 137454359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 137554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1376f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 137754359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 137854359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 137954359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 138054359294a7c9dc54802d512a5d891a35c1663392caryclark break; 138154359294a7c9dc54802d512a5d891a35c1663392caryclark } 1382f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 138354359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 138454359294a7c9dc54802d512a5d891a35c1663392caryclark return; 138554359294a7c9dc54802d512a5d891a35c1663392caryclark } 138654359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 138754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 138854359294a7c9dc54802d512a5d891a35c1663392caryclark} 138954359294a7c9dc54802d512a5d891a35c1663392caryclark 139055888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG 139155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 139255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpGlobalState* debugState) const { 139355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); 139455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); 139555888e44171ffd48b591d19256884a969fe4da17caryclark} 139655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 139726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1398ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 1399ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// sets the span's end to the ptT referenced by the previous-next 1400ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log, 1401ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, 1402ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) const ) const { 1403ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* origPtT = (this->*getEnd)(); 1404ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* origSpan = origPtT->span(); 1405ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = origSpan->prev(); 1406ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = prev ? prev->next()->ptT() 1407ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : origSpan->upCast()->next()->prev()->ptT(); 1408ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (origPtT != testPtT) { 1409ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCorrectEnd_Glitch, this, origPtT, testPtT); 1410ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1411ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1412ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1413ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1414ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* Commented-out lines keep this in sync with correctEnds */ 1415ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// FIXME: member pointers have fallen out of favor and can be replaced with 1416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// an alternative approach. 1417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// makes all span ends agree with the segment's spans that define them 1418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 1419ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTStart, nullptr); 1420ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTEnd, nullptr); 1421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTStart, nullptr); 1422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTEnd, nullptr); 1423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1424ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 142555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */ 142630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// expand the range by checking adjacent spans for coincidence 1427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkCoincidentSpans::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 142855888e44171ffd48b591d19256884a969fe4da17caryclark bool expanded = false; 142955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = coinPtTStart()->segment(); 143055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSegment = oppPtTStart()->segment(); 143155888e44171ffd48b591d19256884a969fe4da17caryclark do { 143255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coinPtTStart()->span()->upCast(); 143355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = start->prev(); 143455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 143555888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev || !(oppPtT = prev->contains(oppSegment))) { 143655888e44171ffd48b591d19256884a969fe4da17caryclark break; 143755888e44171ffd48b591d19256884a969fe4da17caryclark } 143855888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (prev->t() + start->t()) / 2; 143955888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 144055888e44171ffd48b591d19256884a969fe4da17caryclark break; 144155888e44171ffd48b591d19256884a969fe4da17caryclark } 1442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, prev->ptT(), oppPtT); 144355888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 144455888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 144555888e44171ffd48b591d19256884a969fe4da17caryclark do { 144655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coinPtTEnd()->span(); 144755888e44171ffd48b591d19256884a969fe4da17caryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 144830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (next && next->deleted()) { 144930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 145030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 145155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 145255888e44171ffd48b591d19256884a969fe4da17caryclark if (!next || !(oppPtT = next->contains(oppSegment))) { 145355888e44171ffd48b591d19256884a969fe4da17caryclark break; 145455888e44171ffd48b591d19256884a969fe4da17caryclark } 145555888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (end->t() + next->t()) / 2; 145655888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 145755888e44171ffd48b591d19256884a969fe4da17caryclark break; 145855888e44171ffd48b591d19256884a969fe4da17caryclark } 1459ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, next->ptT(), oppPtT); 146055888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 146155888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 146255888e44171ffd48b591d19256884a969fe4da17caryclark return expanded; 146355888e44171ffd48b591d19256884a969fe4da17caryclark} 146455888e44171ffd48b591d19256884a969fe4da17caryclark 1465ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* base, const SkOpSpanBase* testSpan) const { 1467ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = testSpan->ptT(); 1468ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* stopPtT = testPtT; 1469ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* baseSeg = base->segment(); 1470ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark while ((testPtT = testPtT->next()) != stopPtT) { 1471ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* testSeg = testPtT->segment(); 1472ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->deleted()) { 1473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1474ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1475ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testSeg == baseSeg) { 1476ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1477ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1478ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->span()->ptT() != testPtT) { 1479ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1480ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->contains(baseSeg, testSeg, testPtT->fT)) { 1482ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1483ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1484ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // intersect perp with base->ptT() with testPtT->segment() 1485ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDVector dxdy = baseSeg->dSlopeAtT(base->t()); 1486ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkPoint& pt = base->pt(); 1487ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}}; 1488ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkIntersections i; 1489ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i); 1490ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < i.used(); ++index) { 1491ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double t = i[0][index]; 1492ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!between(0, t, 1)) { 1493ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1494ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1495ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDPoint oppPt = i.pt(index); 1496ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oppPt.approximatelyEqual(pt)) { 1497ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1498ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1499ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg); 1500ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPtT* oppStart = writableSeg->addT(t); 1501ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart == testPtT) { 1502ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1503ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1504ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSpan* writableBase = const_cast<SkOpSpan*>(base); 1505ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppStart->span()->addOpp(writableBase); 1506ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart->deleted()) { 1507ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1508ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1509ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* coinSeg = base->segment(); 1510ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* oppSeg = oppStart->segment(); 1511ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double coinTs, coinTe, oppTs, oppTe; 1512ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (Ordered(coinSeg, oppSeg)) { 1513ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = base->t(); 1514ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testSpan->t(); 1515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = oppStart->fT; 1516ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testPtT->fT; 1517ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1518ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinSeg, oppSeg); 1519ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = oppStart->fT; 1520ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testPtT->fT; 1521ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = base->t(); 1522ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testSpan->t(); 1523ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1524ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coinTs > coinTe) { 1525ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinTs, coinTe); 1526ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(oppTs, oppTe); 1527ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1528ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 1529ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added), false) { 1530ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1531ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1532ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1533ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1534ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1535ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1536ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1537ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1538ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* ptT) const { 1539ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!ptT->span()->upCastable(), ptT->span()); 1540ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* base = ptT->span()->upCast(); 1541ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = base->prev(); 1542ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!prev, ptT->span()); 1543ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!prev->isCanceled()) { 1544ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->prev()), false) { 1545ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1546ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1547ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1548ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!base->isCanceled()) { 1549ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->next()), false) { 1550ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1551ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1552ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1553ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1554ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1555ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1556ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* If A is coincident with B and B includes an endpoint, and A's matching point 1557ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark is not the endpoint (i.e., there's an implied line connecting B-end and A) 1558ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark then assume that the same implied line may intersect another curve close to B. 1559ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark Since we only care about coincidence that was undetected, look at the 1560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but 1561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark next door) and see if the A matching point is close enough to form another 1562ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincident pair. If so, check for a new coincident span between B-end/A ptT loop 1563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark and the adjacent ptT loop. 1564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark*/ 1565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const { 1566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* span = fHead; 1567ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span) { 1568ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1569ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1570ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fTop = span; 1571ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fHead = nullptr; 1572ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1573ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) { 1574ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(1 == span->coinPtTStart()->fT, span); 1575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTStart()->fT == 0; 1576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTStart()->fT); 1577ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { // if both are on end, any nearby intersect was already found 1579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTStart()), false) { 1580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTStart()), false) { 1585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1587ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1588ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1589ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) { 1590ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTEnd()->fT == 1; 1591ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT); 1592ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1593ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { 1594ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTEnd()), false) { 1595ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1596ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1597ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1598ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1599ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTEnd()), false) { 1600ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1601ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1602ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1603ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1604ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((span = span->next())); 1605ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this->restoreHead(); 1606ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1607ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1608ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 160955888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */ 161055888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans 161155888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 1612ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddExpanded(SkPathOpsDebug::GlitchLog* log) const { 1613a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark// DEBUG_SET_PHASE(); 161426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 161526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 1616ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1617ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 161826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 161955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* startPtT = coin->coinPtTStart(); 162055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oStartPtT = coin->oppPtTStart(); 1621ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double priorT = startPtT->fT; 1622ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double oPriorT = oStartPtT->fT; 1623ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(startPtT->contains(oStartPtT), coin); 1624ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 162526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 162626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 162755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 162855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 162930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(oEnd->deleted(), coin); 163030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!start->upCastable(), coin); 163126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 1632ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->flipped() && !oStart->upCastable(), coin); 163355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 1634ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 1635ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* seg = start->segment(); 1636ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* oSeg = oStart->segment(); 163726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 1638ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedOpp = test->ptT()->contains(oSeg); 1639ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedThis = oTest->ptT()->contains(seg); 1640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!containedOpp || !containedThis) { 1641ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // choose the ends, or the first common pt-t list shared by both 1642ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double nextT, oNextT; 1643ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (containedOpp) { 1644ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = test->t(); 1645ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = containedOpp->fT; 1646ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (containedThis) { 1647ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = containedThis->fT; 1648ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = oTest->t(); 1649ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // iterate through until a pt-t list found that contains the other 1651ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* walk = test; 1652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* walkOpp; 1653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!walk->upCastable(), coin); 1655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark walk = walk->upCast()->next(); 1656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (!(walkOpp = walk->ptT()->contains(oSeg)) 1657ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark && walk != coin->coinPtTEnd()->span()); 1658a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!walkOpp, coin); 1659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = walk->t(); 1660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = walkOpp->fT; 1661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 166226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 1663a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startRange = nextT - priorT; 166430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!startRange, coin); 1665a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startPart = (test->t() - priorT) / startRange; 1666a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double oStartRange = oNextT - oPriorT; 166730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!oStartRange, coin); 166826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 166930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(startPart == oStartPart, coin); 1670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart 1671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : !!containedThis; 167255888e44171ffd48b591d19256884a969fe4da17caryclark bool startOver = false; 1673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark addToOpp ? log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT + oStartRange * startPart, test) 1675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT + startRange * oStartPart, oTest); 1677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // FAIL_IF(!success, coin); 167855888e44171ffd48b591d19256884a969fe4da17caryclark if (startOver) { 167955888e44171ffd48b591d19256884a969fe4da17caryclark test = start; 168055888e44171ffd48b591d19256884a969fe4da17caryclark oTest = oStart; 168126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1682ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end = coin->coinPtTEnd()->span(); 1683ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oEnd = coin->oppPtTEnd()->span(); 168426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168555888e44171ffd48b591d19256884a969fe4da17caryclark if (test != end) { 1686ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!test->upCastable(), coin); 1687ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT = test->t(); 168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 168926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169055888e44171ffd48b591d19256884a969fe4da17caryclark if (oTest != oEnd) { 1691ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT = oTest->t(); 169255888e44171ffd48b591d19256884a969fe4da17caryclark oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 1693ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 169426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169655888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 169755888e44171ffd48b591d19256884a969fe4da17caryclark return; 169855888e44171ffd48b591d19256884a969fe4da17caryclark} 169955888e44171ffd48b591d19256884a969fe4da17caryclark 170055888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */ 17018016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// note that over1s, over1e, over2s, over2e are ordered 1702ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddIfMissing(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s, 170381a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added, 17048016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* over1e, const SkOpPtT* over2e) const { 17058016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(tStart < tEnd); 17068016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->fT < over1e->fT); 17078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tStart, over1e->fT)); 17088016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 17098016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->fT < over2e->fT); 17108016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tStart, over2e->fT)); 17118016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 17128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over1e->segment()); 17138016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->segment() == over2e->segment()); 17148016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over2s->segment()); 17158016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != coinSeg); 17168016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != oppSeg); 17178016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(coinSeg != oppSeg); 171826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 17198016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 17208016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 17218016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinSeg->collapsed(coinTs, coinTe)) { 1722ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, coinSeg); 172326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 17258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 17268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (oppSeg->collapsed(oppTs, oppTe)) { 1727ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, oppSeg); 172826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinTs > coinTe) { 17308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkTSwap(coinTs, coinTe); 173126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 173226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1733ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added 17348016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ); 173555888e44171ffd48b591d19256884a969fe4da17caryclark} 173655888e44171ffd48b591d19256884a969fe4da17caryclark 173755888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */ 173830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 173930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 1740ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log, 174130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 174281a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double coinTs, double coinTe, double oppTs, double oppTe, bool* added) const { 174355888e44171ffd48b591d19256884a969fe4da17caryclark SkTDArray<SkCoincidentSpans*> overlaps; 1744ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(!fTop); // this is (correctly) reversed in addifMissing() 174581a478ca6c36aac3e53ce0373a281ac8940f4780caryclark if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, 174681a478ca6c36aac3e53ce0373a281ac8940f4780caryclark &overlaps)) { 174755888e44171ffd48b591d19256884a969fe4da17caryclark return; 174855888e44171ffd48b591d19256884a969fe4da17caryclark } 174955888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 175055888e44171ffd48b591d19256884a969fe4da17caryclark coinTe, oppTs, oppTe, &overlaps)) { 175155888e44171ffd48b591d19256884a969fe4da17caryclark return; 175255888e44171ffd48b591d19256884a969fe4da17caryclark } 175355888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 175455888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 175555888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = overlaps[index]; 175655888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 1757ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTStart()); 175855888e44171ffd48b591d19256884a969fe4da17caryclark } 175955888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 1760ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTEnd()); 176155888e44171ffd48b591d19256884a969fe4da17caryclark } 176255888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 176355888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 176455888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 1765ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTStart()); 176655888e44171ffd48b591d19256884a969fe4da17caryclark } 176755888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 176855888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 176955888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 1770ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTEnd()); 177155888e44171ffd48b591d19256884a969fe4da17caryclark } 1772ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!fHead) { this->debugRelease(log, fHead, test); 1773ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, fTop, test); 177455888e44171ffd48b591d19256884a969fe4da17caryclark } 177555888e44171ffd48b591d19256884a969fe4da17caryclark } 177655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 177755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 177830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); 177930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(cs != ce || !cs, coinSeg); 178055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 178155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 178230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); 178355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !cs || !cs->deleted()); 178455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !os || !os->deleted()); 178555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !ce || !ce->deleted()); 178655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !oe || !oe->deleted()); 178755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 178855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 178930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); 179030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && (csExisting == ce || 179130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); 179230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceExisting && (ceExisting == cs || 179330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); 179455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 179555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 179630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); 179730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && (osExisting == oe || 179830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); 179930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeExisting && (oeExisting == os || 180030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oeExisting->contains(osExisting ? osExisting : os)), oppSeg); 180155888e44171ffd48b591d19256884a969fe4da17caryclark bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 180255888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 180355888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !os) { 180455888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs) 1805ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark cs = coinSeg->debugAddT(coinTs, log); 180655888e44171ffd48b591d19256884a969fe4da17caryclark if (!os) 1807ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark os = oppSeg->debugAddT(oppTs, log); 180830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 1809ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (cs && os) cs->span()->debugAddOpp(log, os->span()); 181055888e44171ffd48b591d19256884a969fe4da17caryclark// cs = csWritable; 181130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// os = osWritable->active(); 181230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg); 181355888e44171ffd48b591d19256884a969fe4da17caryclark } 181455888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce || !oe) { 181555888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce) 1816ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ce = coinSeg->debugAddT(coinTe, log); 181755888e44171ffd48b591d19256884a969fe4da17caryclark if (!oe) 1818ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oe = oppSeg->debugAddT(oppTe, log); 1819ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ce && oe) ce->span()->debugAddOpp(log, oe->span()); 182055888e44171ffd48b591d19256884a969fe4da17caryclark// ce = ceWritable; 182155888e44171ffd48b591d19256884a969fe4da17caryclark// oe = oeWritable; 182255888e44171ffd48b591d19256884a969fe4da17caryclark } 182355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 182430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csDeleted, coinSeg); 182530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osDeleted, oppSeg); 182630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceDeleted, coinSeg); 182730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeDeleted, oppSeg); 18288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg); 18298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark bool result = true; 183055888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap) { 183155888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->segment() == coinSeg) { 1832ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 183355888e44171ffd48b591d19256884a969fe4da17caryclark } else { 183455888e44171ffd48b591d19256884a969fe4da17caryclark if (oppTs > oppTe) { 183555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 183655888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(oppTs, oppTe); 183755888e44171ffd48b591d19256884a969fe4da17caryclark } 1838ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 183955888e44171ffd48b591d19256884a969fe4da17caryclark } 18408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (result) { 18428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark overlap->debugShow(); 18438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark } 184455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 184555888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1846ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingCoin_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 18478016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18488016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark fHead->debugShow(); 184955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 185055888e44171ffd48b591d19256884a969fe4da17caryclark } 185155888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 18528016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return (void) result; 185326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 185426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 185555888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing() 185655888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */ 185755888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */ 185855888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again 1859ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddMissing(SkPathOpsDebug::GlitchLog* log, bool* added) const { 186026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 1861ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *added = false; 186226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 186326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 186426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 186555888e44171ffd48b591d19256884a969fe4da17caryclark // fTop = outer; 186655888e44171ffd48b591d19256884a969fe4da17caryclark // fHead = nullptr; 186726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 186826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 186926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 187026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 18718016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ocs = outer->coinPtTStart(); 18728016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ocs->deleted()); 18738016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerCoin = ocs->segment(); 18748016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 18758016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oos = outer->oppPtTStart(); 1876ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oos->deleted()) { 1877ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1878ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 18798016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerOpp = oos->segment(); 18808016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerOpp->done()); 18818016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 18828016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 188326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 188455888e44171ffd48b591d19256884a969fe4da17caryclark while ((inner = inner->next())) { 188555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 188626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 18878016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ics = inner->coinPtTStart(); 18888016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ics->deleted()); 18898016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerCoin = ics->segment(); 18908016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerCoin->done()); 18918016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ios = inner->oppPtTStart(); 18928016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ios->deleted()); 18938016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerOpp = ios->segment(); 18948016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerOpp->done()); 18958016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin); 18968016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 189755888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin == innerCoin) { 18988016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 1899ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oce->deleted()) { 1900ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1901ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 19028016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19038016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 19048016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) { 1905ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ics->starter(ice), 190681a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerOpp, added, 19078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19088016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 190926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 191055888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerCoin == innerOpp) { 19118016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 19128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!oce->deleted()); 19138016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 19148016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ioe->deleted()); 19158016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) { 1916ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ios->starter(ioe), 191781a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerCoin, added, 19188016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19198016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 192026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 192155888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerCoin) { 19228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19238016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 192655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerOpp); 19278016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 1928ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ics->starter(ice), 192981a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerOpp, added, 19308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19318016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 193226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 193355888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerOpp) { 19348016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19358016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19368016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 1937ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ioe->deleted()) { 1938ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1939ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 194055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerCoin); 19418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 1942ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ios->starter(ioe), 194381a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerCoin, added, 19448016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19458016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 194626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 194726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 194855888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 194955888e44171ffd48b591d19256884a969fe4da17caryclark } 195055888e44171ffd48b591d19256884a969fe4da17caryclark } while ((outer = outer->next())); 195155888e44171ffd48b591d19256884a969fe4da17caryclark // this->restoreHead(); 195255888e44171ffd48b591d19256884a969fe4da17caryclark return; 195355888e44171ffd48b591d19256884a969fe4da17caryclark} 195455888e44171ffd48b591d19256884a969fe4da17caryclark 195555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release() 1956ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { 195730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 195830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* prev = nullptr; 195930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* next; 196030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 196130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark next = coin->next(); 196230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (coin == remove) { 196330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (prev) { 196430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// prev->setNext(next); 196530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else if (head == fHead) { 196630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fHead = next; 196730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 196830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fTop = next; 196930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 1970ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 197130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 197230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark prev = coin; 197330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((coin = next)); 197430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 197530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 197630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 1977ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 197855888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 197955888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 198055888e44171ffd48b591d19256884a969fe4da17caryclark return; 198155888e44171ffd48b591d19256884a969fe4da17caryclark } 198255888e44171ffd48b591d19256884a969fe4da17caryclark do { 198355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->segment() == deleted 198455888e44171ffd48b591d19256884a969fe4da17caryclark || coin->coinPtTEnd()->segment() == deleted 198555888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTStart()->segment() == deleted 198655888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTEnd()->segment() == deleted) { 1987ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 198830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 198955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 199026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 199126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 199255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand() 199355888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence 1994ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkOpCoincidence::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 199526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 199626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 199726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 199826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 199926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 200026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2001ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coin->debugExpand(log)) { 200255888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if multiple spans expanded so they are now identical 200355888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = fHead; 200455888e44171ffd48b591d19256884a969fe4da17caryclark do { 200555888e44171ffd48b591d19256884a969fe4da17caryclark if (coin == test) { 200655888e44171ffd48b591d19256884a969fe4da17caryclark continue; 200755888e44171ffd48b591d19256884a969fe4da17caryclark } 200855888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == test->coinPtTStart() 200955888e44171ffd48b591d19256884a969fe4da17caryclark && coin->oppPtTStart() == test->oppPtTStart()) { 2010ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, fHead, test->coinPtTStart()); 201155888e44171ffd48b591d19256884a969fe4da17caryclark break; 201255888e44171ffd48b591d19256884a969fe4da17caryclark } 201355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next())); 201455888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 201526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 201655888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 201726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 201826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 201926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 202055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark() 202155888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 2022ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMark(SkPathOpsDebug::GlitchLog* log) const { 202326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 202426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 202526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 202626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 202726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2028ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable(), coin); 202955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 203055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(start->deleted()); 203155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 203255888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(end->deleted()); 203355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 203455888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oStart->deleted()); 203555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 203655888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oEnd->deleted()); 203755888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 203826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 203926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 204026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 204155888e44171ffd48b591d19256884a969fe4da17caryclark /* coin and opp spans may not match up. Mark the ends, and then let the interior 204255888e44171ffd48b591d19256884a969fe4da17caryclark get marked as many times as the spans allow */ 2043ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark start->debugInsertCoincidence(log, oStart->upCast()); 2044ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end->debugInsertCoinEnd(log, oEnd); 204555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = start->segment(); 204655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oSegment = oStart->segment(); 204726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 204826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 2049a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark bool ordered; 2050a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!coin->ordered(&ordered), coin); 205155888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->upCast()->next()) != end) { 2052ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!next->upCastable(), coin); 2053ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (next->upCast()->debugInsertCoincidence(log, oSegment, flipped, ordered), false) { 205455888e44171ffd48b591d19256884a969fe4da17caryclark return; 205526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 205655888e44171ffd48b591d19256884a969fe4da17caryclark } 205755888e44171ffd48b591d19256884a969fe4da17caryclark while ((oNext = oNext->upCast()->next()) != oEnd) { 2058ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oNext->upCastable(), coin); 2059ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oNext->upCast()->debugInsertCoincidence(log, segment, flipped, ordered), false) { 206055888e44171ffd48b591d19256884a969fe4da17caryclark return; 206126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 206255888e44171ffd48b591d19256884a969fe4da17caryclark } 206355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 206455888e44171ffd48b591d19256884a969fe4da17caryclark return; 206555888e44171ffd48b591d19256884a969fe4da17caryclark} 206655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 206755888e44171ffd48b591d19256884a969fe4da17caryclark 2068ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 206955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2070ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 207130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 207255888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 207355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->collapsed(test)) { 207455888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 2075ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 207626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 207755888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 2078ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 207955888e44171ffd48b591d19256884a969fe4da17caryclark } 2080ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, head, coin); 208155888e44171ffd48b591d19256884a969fe4da17caryclark } 208255888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 208355888e44171ffd48b591d19256884a969fe4da17caryclark } 208455888e44171ffd48b591d19256884a969fe4da17caryclark} 208555888e44171ffd48b591d19256884a969fe4da17caryclark 208655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2087ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 2088ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fHead, test); 2089ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fTop, test); 209026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 209126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 209226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 209355888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const { 20946c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(), 209555888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->fT, coinPtTEnd()->fT); 20966c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(), 209755888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->fT, oppPtTEnd()->fT); 209855888e44171ffd48b591d19256884a969fe4da17caryclark} 209955888e44171ffd48b591d19256884a969fe4da17caryclark 2100624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 210155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 210255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* span = fHead; 2103624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 210455888e44171ffd48b591d19256884a969fe4da17caryclark span->debugShow(); 210555888e44171ffd48b591d19256884a969fe4da17caryclark span = span->next(); 2106624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 210755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2108624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2109624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 2110ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 21116c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end, 211255888e44171ffd48b591d19256884a969fe4da17caryclark double oStart, double oEnd, const SkOpSegment* oSegment, 2113ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 211455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(next != end); 211555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!next->contains(end) || log); 211655888e44171ffd48b591d19256884a969fe4da17caryclark if (next->t() > end->t()) { 211755888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(next, end); 211855888e44171ffd48b591d19256884a969fe4da17caryclark } 211955888e44171ffd48b591d19256884a969fe4da17caryclark do { 212055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = next->ptT(); 212155888e44171ffd48b591d19256884a969fe4da17caryclark int index = 0; 212227c015dfcf4e2b8fb1abe327cc40204e2a4f452acaryclark bool somethingBetween = false; 212355888e44171ffd48b591d19256884a969fe4da17caryclark do { 212455888e44171ffd48b591d19256884a969fe4da17caryclark ++index; 212555888e44171ffd48b591d19256884a969fe4da17caryclark ptT = ptT->next(); 212655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* checkPtT = next->ptT(); 212755888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT == checkPtT) { 212855888e44171ffd48b591d19256884a969fe4da17caryclark break; 212955888e44171ffd48b591d19256884a969fe4da17caryclark } 213055888e44171ffd48b591d19256884a969fe4da17caryclark bool looped = false; 213155888e44171ffd48b591d19256884a969fe4da17caryclark for (int check = 0; check < index; ++check) { 213255888e44171ffd48b591d19256884a969fe4da17caryclark if ((looped = checkPtT == ptT)) { 213355888e44171ffd48b591d19256884a969fe4da17caryclark break; 213455888e44171ffd48b591d19256884a969fe4da17caryclark } 213555888e44171ffd48b591d19256884a969fe4da17caryclark checkPtT = checkPtT->next(); 213655888e44171ffd48b591d19256884a969fe4da17caryclark } 213755888e44171ffd48b591d19256884a969fe4da17caryclark if (looped) { 213855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 213955888e44171ffd48b591d19256884a969fe4da17caryclark break; 214055888e44171ffd48b591d19256884a969fe4da17caryclark } 214155888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->deleted()) { 214255888e44171ffd48b591d19256884a969fe4da17caryclark continue; 214355888e44171ffd48b591d19256884a969fe4da17caryclark } 214455888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() != oSegment) { 214555888e44171ffd48b591d19256884a969fe4da17caryclark continue; 214655888e44171ffd48b591d19256884a969fe4da17caryclark } 214755888e44171ffd48b591d19256884a969fe4da17caryclark somethingBetween |= between(oStart, ptT->fT, oEnd); 214855888e44171ffd48b591d19256884a969fe4da17caryclark } while (true); 214955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(somethingBetween); 215055888e44171ffd48b591d19256884a969fe4da17caryclark } while (next != end && (next = next->upCast()->next())); 215155888e44171ffd48b591d19256884a969fe4da17caryclark} 215255888e44171ffd48b591d19256884a969fe4da17caryclark 215355888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 2154ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 215555888e44171ffd48b591d19256884a969fe4da17caryclark if (!list) { 215655888e44171ffd48b591d19256884a969fe4da17caryclark return; 215755888e44171ffd48b591d19256884a969fe4da17caryclark } 215855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 215955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 216055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 216155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 216255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg != test->oppPtTStart()->segment()); 216355888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 216455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tcs, 1)); 216555888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 216655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tce, 1)); 216755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tcs < tce); 216855888e44171ffd48b591d19256884a969fe4da17caryclark double tos = test->oppPtTStart()->fT; 216955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tos, 1)); 217055888e44171ffd48b591d19256884a969fe4da17caryclark double toe = test->oppPtTEnd()->fT; 217155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, toe, 1)); 217255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tos != toe); 217355888e44171ffd48b591d19256884a969fe4da17caryclark if (tos > toe) { 217455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(tos, toe); 217555888e44171ffd48b591d19256884a969fe4da17caryclark } 217655888e44171ffd48b591d19256884a969fe4da17caryclark do { 217755888e44171ffd48b591d19256884a969fe4da17caryclark double lcs, lce, los, loe; 217855888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == list->coinPtTStart()->segment()) { 217955888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->oppPtTStart()->segment()) { 218055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 218155888e44171ffd48b591d19256884a969fe4da17caryclark } 218255888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->coinPtTStart()->fT; 218355888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->coinPtTEnd()->fT; 218455888e44171ffd48b591d19256884a969fe4da17caryclark los = list->oppPtTStart()->fT; 218555888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->oppPtTEnd()->fT; 218655888e44171ffd48b591d19256884a969fe4da17caryclark if (los > loe) { 218755888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(los, loe); 218855888e44171ffd48b591d19256884a969fe4da17caryclark } 218955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (coinSeg == list->oppPtTStart()->segment()) { 219055888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->coinPtTStart()->segment()) { 219155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 219255888e44171ffd48b591d19256884a969fe4da17caryclark } 219355888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->oppPtTStart()->fT; 219455888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->oppPtTEnd()->fT; 219555888e44171ffd48b591d19256884a969fe4da17caryclark if (lcs > lce) { 219655888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(lcs, lce); 219755888e44171ffd48b591d19256884a969fe4da17caryclark } 219855888e44171ffd48b591d19256884a969fe4da17caryclark los = list->coinPtTStart()->fT; 219955888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->coinPtTEnd()->fT; 220055888e44171ffd48b591d19256884a969fe4da17caryclark } else { 220155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 220255888e44171ffd48b591d19256884a969fe4da17caryclark } 220355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tce < lcs || lce < tcs); 220455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(toe < los || loe < tos); 220555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((list = list->next())); 220655888e44171ffd48b591d19256884a969fe4da17caryclark} 220755888e44171ffd48b591d19256884a969fe4da17caryclark 220855888e44171ffd48b591d19256884a969fe4da17caryclark 220955888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2210ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 221155888e44171ffd48b591d19256884a969fe4da17caryclark // check for overlapping coincident spans 221255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = head; 221355888e44171ffd48b591d19256884a969fe4da17caryclark while (test) { 221455888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* next = test->next(); 2215ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, next, log); 2216ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, opt, log); 221755888e44171ffd48b591d19256884a969fe4da17caryclark test = next; 221855888e44171ffd48b591d19256884a969fe4da17caryclark } 221955888e44171ffd48b591d19256884a969fe4da17caryclark} 222055888e44171ffd48b591d19256884a969fe4da17caryclark 222155888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2222ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 222355888e44171ffd48b591d19256884a969fe4da17caryclark // look for pts inside coincident spans that are not inside the opposite spans 222455888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = head; 222555888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 222655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 222755888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->segment())); 222855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 222955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 223055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 223155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 22326c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark coin = coin->next(); 22336c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 22356c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22366c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22376c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 22386c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugValidate() const { 22396c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if DEBUG_COINCIDENCE 2240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, nullptr); 2241ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, nullptr); 22426c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22436c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22446c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 2245ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 22466c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2247ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 22486c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark // look for pts inside coincident spans that are not inside the opposite spans 22496c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark const SkCoincidentSpans* coin = head; 22506c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark while (coin) { 22516c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 225255888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 2253ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 22546c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 225555888e44171ffd48b591d19256884a969fe4da17caryclark coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 2256ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 225755888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 225855888e44171ffd48b591d19256884a969fe4da17caryclark } 2259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 226055888e44171ffd48b591d19256884a969fe4da17caryclark} 226155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 226255888e44171ffd48b591d19256884a969fe4da17caryclark 22636c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugCheckBetween() const { 226455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 22656c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark if (fGlobalState->debugCheckHealth()) { 22666c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark return; 22676c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fHead, fTop, nullptr); 2269ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fTop, nullptr, nullptr); 227055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 227155888e44171ffd48b591d19256884a969fe4da17caryclark} 227255888e44171ffd48b591d19256884a969fe4da17caryclark 2273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugCheckHealth(SkPathOpsDebug::GlitchLog* log) const { 2275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugCheckHealth(log); 2278ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 227955888e44171ffd48b591d19256884a969fe4da17caryclark} 2280ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCheckValid(SkPathOpsDebug::GlitchLog* log) const { 2282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 2283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, log); 2284ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, log); 228555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 228755888e44171ffd48b591d19256884a969fe4da17caryclark 2288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 2289ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* coin = fHead; 2290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!coin) { 2291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 229326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coin->debugCorrectEnds(log); 2295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((coin = coin->next())); 229626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 229726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 229855888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence() 2299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 230055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fCount > 0); 230126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 230255888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 230326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2304e47ae2998c1cf944db5743a416583dd0f042b6d9Cary Clark if (segment->debugMissingCoincidence(log), false) { 230555888e44171ffd48b591d19256884a969fe4da17caryclark// result = true; 230655888e44171ffd48b591d19256884a969fe4da17caryclark } 230755888e44171ffd48b591d19256884a969fe4da17caryclark segment = segment->next(); 230855888e44171ffd48b591d19256884a969fe4da17caryclark } while (segment); 230955888e44171ffd48b591d19256884a969fe4da17caryclark return; 231026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 2311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveMultiples(SkPathOpsDebug::GlitchLog* log) const { 2313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (segment->debugMoveMultiples(log), false) { 2317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2318ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2319ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2320ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2321ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 2322ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2323ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const { 2324ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2325ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2326ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2327ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugMoveNearby(log); 2328ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2329ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 233026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 233126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2332025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2333025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugResetCoinT() const { 2334025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = -1; 2335025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = 1; 2336025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = -1; 2337025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = -1; 2338025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = 1; 2339025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = -1; 2340025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2341025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2342025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 23434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 2344025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2345025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark { 2346025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpSpanBase* span = &fHead; 2347025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2348025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugResetCoinT(); 2349025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2350025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span = &fHead; 2351025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark int index = 0; 2352025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2353025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugSetCoinT(index++); 2354025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2355025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2356025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 235755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 235855888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 235955888e44171ffd48b591d19256884a969fe4da17caryclark return; 236055888e44171ffd48b591d19256884a969fe4da17caryclark } 236155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 23624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 236354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 236454359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 236596fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 236654359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 23674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 236854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 236954359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 237054359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 237154359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 237254359294a7c9dc54802d512a5d891a35c1663392caryclark } 237354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 237454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 237554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 237654359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 237754359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 237854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 237954359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 238054359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 238154359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 238254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 238354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 238408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 238554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 238654359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 238754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 238854359294a7c9dc54802d512a5d891a35c1663392caryclark} 238954359294a7c9dc54802d512a5d891a35c1663392caryclark 2390ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 239130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 239230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with addOpp() 2393ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugAddOpp(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 239430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 239530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!oppPrev) { 239655888e44171ffd48b591d19256884a969fe4da17caryclark return; 239726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2398ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMergeMatches(log, opp); 239930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->ptT()->debugAddOpp(opp->ptT(), oppPrev); 2400ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 240126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 240226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 240355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 2404ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* log) const { 240555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coins = this->globalState()->coincidence(); 240655888e44171ffd48b591d19256884a969fe4da17caryclark if (coins->isEmpty()) { 240755888e44171ffd48b591d19256884a969fe4da17caryclark return; 240855888e44171ffd48b591d19256884a969fe4da17caryclark } 240955888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span 241055888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop 241155888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span 241255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 241355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* test = head; 241426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 241555888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->coincident()) { 241655888e44171ffd48b591d19256884a969fe4da17caryclark continue; 241726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coins->debugMarkCollapsed(log, test); 241955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next()) != head); 242026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 242155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 242226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 242354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 242454359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 242554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 242654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 242754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 242854359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 242954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 243054359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 243154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 243254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 243354359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 243454359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 243554359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 243654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 243754359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 243854359294a7c9dc54802d512a5d891a35c1663392caryclark } 243954359294a7c9dc54802d512a5d891a35c1663392caryclark } 244054359294a7c9dc54802d512a5d891a35c1663392caryclark } 244154359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 244254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 244354359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 244454359294a7c9dc54802d512a5d891a35c1663392caryclark} 244554359294a7c9dc54802d512a5d891a35c1663392caryclark 2446ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 244755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd() 2448ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 244955888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoinEnd(coin)) { 245055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoinEnd(this)); 245155888e44171ffd48b591d19256884a969fe4da17caryclark return; 245255888e44171ffd48b591d19256884a969fe4da17caryclark } 245355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 245455888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2455ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinEnd_Glitch, this, coin); 245655888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoinEnd = this->fCoinEnd; 245755888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoinEnd = coinNext; 245855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 245955888e44171ffd48b591d19256884a969fe4da17caryclark} 246055888e44171ffd48b591d19256884a969fe4da17caryclark 246130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with mergeMatches() 246230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Look to see if pt-t linked list contains same segment more than once 246330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if so, and if each pt-t is directly pointed to by spans in that segment, 246430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// merge them 246530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// keep the points, but remove spans so that the segment doesn't have 2 or more 246630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// spans pointing to the same pt-t loop at different loop elements 2467ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugMergeMatches(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 246830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* test = &fPtT; 246930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* testNext; 247030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* stop = test; 247130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 247230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark testNext = test->next(); 247330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (test->deleted()) { 247430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 247530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 247630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* testBase = test->span(); 247730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(testBase->ptT() == test); 247830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* segment = test->segment(); 247930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (segment->done()) { 248030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 248130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 248230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* inner = opp->ptT(); 248330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* innerStop = inner; 248430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 248530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->segment() != segment) { 248630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 248730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 248830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->deleted()) { 248930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 249030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 249130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* innerBase = inner->span(); 249230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(innerBase->ptT() == inner); 249330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // when the intersection is first detected, the span base is marked if there are 249430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // more than one point in the intersection. 249530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) { 249630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(inner->fT)) { 2497ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, innerBase, test); 249830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 249930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(inner->fT != test->fT); 250030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(test->fT)) { 2501ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, testBase, inner); 250230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 2503ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, segment); 250430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(testBase->debugSetDeleted()); 250530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// test->setDeleted(); 250630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(innerBase->debugSetDeleted()); 250730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// inner->setDeleted(); 250830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 251030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#ifdef SK_DEBUG // assert if another undeleted entry points to segment 251130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* debugInner = inner; 251230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark while ((debugInner = debugInner->next()) != innerStop) { 251330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->segment() != segment) { 251430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 251530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 251630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->deleted()) { 251730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 251830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 251930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkOPASSERT(0); 252030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 252130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#endif 252230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 252330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// } 252430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 252530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((inner = inner->next()) != innerStop); 252630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((test = testNext) != stop); 2527ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 252830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 252930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 253055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 253126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2532025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugResetCoinT() const { 2533025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2534025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2535025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2536025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugResetCoinT(); 2537025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2538025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2539025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2540025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2541025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2542025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugSetCoinT(int index) const { 2543025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2544025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2545025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2546025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (!ptT->deleted()) { 2547025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugSetCoinT(index); 2548025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2549025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2550025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2551025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2552025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2553025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 255426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 255526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 255626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 255726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 255826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 255926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 256026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 256126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 256226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 256326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 256426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 256526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 256626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 256754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 256855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 256955888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 257055888e44171ffd48b591d19256884a969fe4da17caryclark return; 257155888e44171ffd48b591d19256884a969fe4da17caryclark } 257255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 257354359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 257454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 257554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 257654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 257754359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 257854359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 257954359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 258054359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 258154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 258254359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 258354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 258454359294a7c9dc54802d512a5d891a35c1663392caryclark } 258554359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 258654359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 258754359294a7c9dc54802d512a5d891a35c1663392caryclark } 258854359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 258954359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 259054359294a7c9dc54802d512a5d891a35c1663392caryclark } 25914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 259254359294a7c9dc54802d512a5d891a35c1663392caryclark} 259354359294a7c9dc54802d512a5d891a35c1663392caryclark 259454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 259554359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 259654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 259754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 259854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 259954359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 260054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 260154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 260254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 260354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 260454359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 260554359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 260654359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 260754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 260854359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 260954359294a7c9dc54802d512a5d891a35c1663392caryclark } 261054359294a7c9dc54802d512a5d891a35c1663392caryclark } 261154359294a7c9dc54802d512a5d891a35c1663392caryclark } 261254359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 261354359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 261454359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 261554359294a7c9dc54802d512a5d891a35c1663392caryclark} 261654359294a7c9dc54802d512a5d891a35c1663392caryclark 2617ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 261855888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header 2619ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 262055888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoincidence(coin)) { 262155888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoincidence(this)); 262255888e44171ffd48b591d19256884a969fe4da17caryclark return; 262355888e44171ffd48b591d19256884a969fe4da17caryclark } 262455888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 262555888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2626ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinStart_Glitch, this, coin); 262755888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoincident = this->fCoincident; 262855888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoincident = coinNext; 262955888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 263055888e44171ffd48b591d19256884a969fe4da17caryclark} 263155888e44171ffd48b591d19256884a969fe4da17caryclark 263255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() 2633ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped, bool ordered) const { 263455888e44171ffd48b591d19256884a969fe4da17caryclark if (this->containsCoincidence(segment)) { 263555888e44171ffd48b591d19256884a969fe4da17caryclark return; 263655888e44171ffd48b591d19256884a969fe4da17caryclark } 263755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* next = &fPtT; 263855888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->next()) != &fPtT) { 263955888e44171ffd48b591d19256884a969fe4da17caryclark if (next->segment() == segment) { 2640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* span; 2641ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* base = next->span(); 2642ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!ordered) { 2643ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* spanEnd = fNext->contains(segment)->span(); 2644ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT()); 2645ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!start->span()->upCastable(), this); 2646ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = const_cast<SkOpSpan*>(start->span()->upCast()); 2647ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2648ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else if (flipped) { 2649ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->prev(); 2650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!span, this); 2651ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else { 2653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!base->upCastable(), this); 2654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->upCast(); 2655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinInsert_Glitch, span); 265755888e44171ffd48b591d19256884a969fe4da17caryclark return; 265855888e44171ffd48b591d19256884a969fe4da17caryclark } 265955888e44171ffd48b591d19256884a969fe4da17caryclark } 2660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinMissing_Glitch, segment, this); 266255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 266455888e44171ffd48b591d19256884a969fe4da17caryclark} 266555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 266655888e44171ffd48b591d19256884a969fe4da17caryclark 2667624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 2668624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 2669624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 2670624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 2671624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 2672624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2673624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 2674624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 2675624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 2676624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 2677624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 2678624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2679624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 2680624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 2681624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 2682624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2683624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 2684624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2685624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 2686624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 2687624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2688624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 268954359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 269054359294a7c9dc54802d512a5d891a35c1663392caryclark 269155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp() 269229b2563afb1677515739f1d24fb27733626eca92caryclarkvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { 269329b2563afb1677515739f1d24fb27733626eca92caryclark SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); 269455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(this != opp); 269555888e44171ffd48b591d19256884a969fe4da17caryclark// this->fNext = opp; 269629b2563afb1677515739f1d24fb27733626eca92caryclark SkASSERT(oppPrev != oldNext); 269755888e44171ffd48b591d19256884a969fe4da17caryclark// oppPrev->fNext = oldNext; 269855888e44171ffd48b591d19256884a969fe4da17caryclark} 269955888e44171ffd48b591d19256884a969fe4da17caryclark 270026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 270126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 270226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 270326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 270426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 270526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 270626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 270726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 270826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 270926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 271026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 271126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 271226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 271326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 271426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 271526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 271626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 271726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 271826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 271926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 272026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 272126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 272226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 272326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 272426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 272526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 272626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 272726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 272826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 272926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 273026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 273126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 273226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 273326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 273426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 273626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 273826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 273926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 27408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclarkconst SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const { 27418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return fT < end->fT ? end : this; 27428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark} 27438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark 274454359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 274554359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 274654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 274754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 274854359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 274954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 275054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 275154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 275254359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 275354359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 275454359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 275554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 275654359294a7c9dc54802d512a5d891a35c1663392caryclark } 275754359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 275854359294a7c9dc54802d512a5d891a35c1663392caryclark } 27594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 27604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 276126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 276226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 276326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 276426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 276526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 276626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 276726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 276854359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 276954359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 277054359294a7c9dc54802d512a5d891a35c1663392caryclark} 277154359294a7c9dc54802d512a5d891a35c1663392caryclark 277229b2563afb1677515739f1d24fb27733626eca92caryclarkconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { 277329b2563afb1677515739f1d24fb27733626eca92caryclark return this->oppPrev(const_cast<SkOpPtT*>(opp)); 277429b2563afb1677515739f1d24fb27733626eca92caryclark} 277529b2563afb1677515739f1d24fb27733626eca92caryclark 2776025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugResetCoinT() const { 2777025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2778025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugResetCoinT(); 2779025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2780025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2781025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2782025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugSetCoinT(int index) const { 2783025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2784025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugSetCoinT(index, fT); 2785025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2786025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2787025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 278854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 278955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 279055888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 279155888e44171ffd48b591d19256884a969fe4da17caryclark return; 279255888e44171ffd48b591d19256884a969fe4da17caryclark } 279355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 279454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 2795ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPhase phase = contour()->globalState()->phase(); 2796ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (phase == SkOpPhase::kIntersecting || phase == SkOpPhase::kFixWinding) { 279754359294a7c9dc54802d512a5d891a35c1663392caryclark return; 27984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 279954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 280054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 280154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 280254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 28034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 28044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 28051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28061049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 28071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 28081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 28091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 28101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 28111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 28121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 28131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 28141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 28151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 28161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 28181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 28191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28221049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 28231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 28241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 28251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 28271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 28281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28331049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 28341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 28351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 28361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 28371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 28381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 28391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 28401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 28411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 28431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 28441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 28451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 28461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 28491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 28501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 28541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 28551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 28571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 28591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 28601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 28611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 28641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 28651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 28671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 28681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 28691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28731049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 28741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 28751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 28761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 28771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 28781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 28791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28801049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 28811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 28821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 28831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 288496fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 28851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 28861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 28871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 28881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 28891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 28901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 28911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 28921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 28931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 28941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 28951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 28961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 28981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 29001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 29011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 29021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 29031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 29041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 29051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 29061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 29071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 29081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 2909