SkPathOpsDebug.cpp revision 918fb1fe6ff5349a2d1e5fb6872139f5fb931480
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc. 307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * 407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file. 607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h" 926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h" 1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h" 111326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkOSFile.h" 1202802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h" 131b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h" 1454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h" 1554359294a7c9dc54802d512a5d891a35c1663392caryclark 16918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY 171326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gDumpOp; // set to true to write op to file before a crash 181326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVerifyOp; // set to true to compare result against regions 191326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif 201326068147ee60de138061a3fc1157fcfd5d017bcaryclark 211326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gRunFail; // set to true to check for success on tests known to fail 221326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVeryVerbose; // set to true to run extensive checking tests 231326068147ee60de138061a3fc1157fcfd5d017bcaryclark 2430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_IF 2530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_IF(cond, coin) \ 26ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false) 2730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_WITH_NULL_IF 2930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_WITH_NULL_IF(cond, span) \ 30ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, span); } while (false) 3130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 3230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef RETURN_FALSE_IF 3330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define RETURN_FALSE_IF(cond, span) \ 34ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kReturnFalse_Glitch, span); \ 35ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (false) 3630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 3755888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans; 3826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 39624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 40624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 41624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 42624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 43624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 44624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 45624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 46624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 47624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 50570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 52fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 53fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 54570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 5654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 5854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 6626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 67ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 6826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 69ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumChangedDict; 70ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumVisitedDict; 71ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 72ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic const int kGlitchType_Count = SkPathOpsDebug::kUnalignedTail_Glitch + 1; 7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 7426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 7526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 7626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 7855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* fOppSegment; 7926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 8026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 8355888e44171ffd48b591d19256884a969fe4da17caryclark double fStartT; 8455888e44171ffd48b591d19256884a969fe4da17caryclark double fEndT; 8555888e44171ffd48b591d19256884a969fe4da17caryclark double fOppStartT; 8655888e44171ffd48b591d19256884a969fe4da17caryclark double fOppEndT; 8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 88ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchType fType; 89ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 90ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void dumpType() const; 9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 9226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 94ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void init(const SkOpGlobalState* state) { 95ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fGlobalState = state; 96ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 97ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 98ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* recordCommon(GlitchType type) { 9926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 10026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 10126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 10355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = nullptr; 10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 10855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = SK_ScalarNaN; 10955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = SK_ScalarNaN; 11055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = SK_ScalarNaN; 11155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = SK_ScalarNaN; 11226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 11326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 11426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 117ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 119ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 12126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 124ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 12555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 126ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 12755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 12855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = ptT; 12955888e44171ffd48b591d19256884a969fe4da17caryclark } 13055888e44171ffd48b591d19256884a969fe4da17caryclark 131ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 13255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* opp = NULL) { 133ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 13455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 13555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 13655888e44171ffd48b591d19256884a969fe4da17caryclark if (opp) { 13755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = opp->coinPtTStart(); 13855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = opp->coinPtTEnd(); 13955888e44171ffd48b591d19256884a969fe4da17caryclark } 14026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 142ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 144ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 14626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 14755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 14826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 151ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, double t, 15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 153ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 15555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 15726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 159ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 161ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 16255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 16355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 16555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = coinSpan; 16655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = endSpan; 16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 169ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 17055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* base) { 171ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 17255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 17355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 17455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 17526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 177ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 179ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 18326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 186ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, double startT, 18755888e44171ffd48b591d19256884a969fe4da17caryclark double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 188ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 18955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 19055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = startT; 19155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = endT; 19255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = oppSeg; 19355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = oppStartT; 19455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = oppEndT; 19555888e44171ffd48b591d19256884a969fe4da17caryclark } 19655888e44171ffd48b591d19256884a969fe4da17caryclark 197ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, 19855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span) { 199ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 20055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 20155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 20255888e44171ffd48b591d19256884a969fe4da17caryclark } 20355888e44171ffd48b591d19256884a969fe4da17caryclark 204ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, double t, const SkOpSpanBase* span) { 205ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 20655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 20755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 20855888e44171ffd48b591d19256884a969fe4da17caryclark } 20955888e44171ffd48b591d19256884a969fe4da17caryclark 210ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg) { 211ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 21255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 21355888e44171ffd48b591d19256884a969fe4da17caryclark } 21455888e44171ffd48b591d19256884a969fe4da17caryclark 215ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 21655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 217ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 21855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 21955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = ptT; 22055888e44171ffd48b591d19256884a969fe4da17caryclark } 22155888e44171ffd48b591d19256884a969fe4da17caryclark 22226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 223ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpGlobalState* fGlobalState; 22426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 225ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 226ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 227ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const SkPathOpsDebug::CoinDict& dict) { 228ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = dict.fDict.count(); 229ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 230ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->add(dict.fDict[index]); 231ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 232ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const CoinDictEntry& key) { 235ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = fDict.count(); 236ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 237ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark CoinDictEntry* entry = &fDict[index]; 238ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fIteration == key.fIteration && entry->fLineNumber == key.fLineNumber) { 239ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(!strcmp(entry->fFunctionName, key.fFunctionName)); 240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fGlitchType == kUninitialized_Glitch) { 241ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = key.fGlitchType; 242ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 243ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 244ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 245ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 246ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *fDict.append() = key; 247ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 248ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 249ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 250ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 251ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void missing_coincidence(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 253ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 254ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // bool result = false; 255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 256ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark /* result |= */ contour->debugMissingCoincidence(glitches); 257ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 260ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 261ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_multiples(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 262ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 263ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 264ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (contour->debugMoveMultiples(glitches), false) { 265ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 266ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 269ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 270ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 271ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_nearby(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 272ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMoveNearby(glitches); 275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 278ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 279ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 280ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToCoinChangedDict() { 283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 284ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 285e6522ea38fa3bcfdf2d718ea5ad898b3b3d46e00caryclark SkPathOpsDebug::CheckHealth(fContourHead); 286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // see if next coincident operation makes a change; if so, record it 288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog glitches; 289ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const char* funcName = fCoinDictEntry.fFunctionName; 290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!strcmp("calc_angles", funcName)) { 291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("missing_coincidence", funcName)) { 293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark missing_coincidence(&glitches, fContourHead); 294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_multiples", funcName)) { 295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_multiples(&glitches, fContourHead); 296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_nearby", funcName)) { 297ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_nearby(&glitches, fContourHead); 298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addExpanded", funcName)) { 299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddExpanded(&glitches); 300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addMissing", funcName)) { 301ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddMissing(&glitches, &added); 303ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addEndMovedSpans", funcName)) { 304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddEndMovedSpans(&glitches); 305ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("correctEnds", funcName)) { 306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugCorrectEnds(&glitches); 307ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("expand", funcName)) { 308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugExpand(&glitches); 309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("findOverlaps", funcName)) { 310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("mark", funcName)) { 312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugMark(&glitches); 313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("apply", funcName)) { 314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(0); // add missing case 317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 318ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (glitches.fGlitches.count()) { 319ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinDictEntry.fGlitchType = glitches.fGlitches[0].fType; 320ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 321ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinChangedDict.add(fCoinDictEntry); 322ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 32355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 32426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 32555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 32655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 32755888e44171ffd48b591d19256884a969fe4da17caryclark SkOpContour* contour = contourList; 32855888e44171ffd48b591d19256884a969fe4da17caryclark do { 32955888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugShowActiveSpans(); 33055888e44171ffd48b591d19256884a969fe4da17caryclark } while ((contour = contour->next())); 33155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 33255888e44171ffd48b591d19256884a969fe4da17caryclark} 33355888e44171ffd48b591d19256884a969fe4da17caryclark 334ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE || DEBUG_COIN 335ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList) { 33655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 33755888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(true); 338ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 339ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 34026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 34126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 34226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 343ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugCheckValid(&glitches); // don't call validate; spans may be inconsistent 34426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 345ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugCheckHealth(&glitches); 346ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMissingCoincidence(&glitches); 34726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 34881a478ca6c36aac3e53ce0373a281ac8940f4780caryclark bool added; 349ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddMissing(&glitches, &added); 350ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugExpand(&glitches); 351ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddExpanded(&glitches); 352ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugMark(&glitches); 35326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 35626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 35726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 35926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 36026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 36155888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 36255888e44171ffd48b591d19256884a969fe4da17caryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 36355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%02d: ", index); 36455888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fBase) { 3658016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(), 3668016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fBase->debugID()); 36755888e44171ffd48b591d19256884a969fe4da17caryclark } 36855888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSuspect) { 3698016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(), 3708016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fSuspect->debugID()); 37155888e44171ffd48b591d19256884a969fe4da17caryclark } 37255888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSegment) { 37355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fSegment->debugID()); 37455888e44171ffd48b591d19256884a969fe4da17caryclark } 37555888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fCoinSpan) { 3768016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(), 3778016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID()); 37855888e44171ffd48b591d19256884a969fe4da17caryclark } 37955888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fEndSpan) { 38055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 38155888e44171ffd48b591d19256884a969fe4da17caryclark } 38255888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSpan) { 3838016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(), 3848016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID()); 38555888e44171ffd48b591d19256884a969fe4da17caryclark } 38655888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppEndSpan) { 38755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 38855888e44171ffd48b591d19256884a969fe4da17caryclark } 38955888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fStartT)) { 39055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" startT=%g", glitch.fStartT); 39155888e44171ffd48b591d19256884a969fe4da17caryclark } 39255888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fEndT)) { 39355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endT=%g", glitch.fEndT); 39455888e44171ffd48b591d19256884a969fe4da17caryclark } 39555888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSegment) { 39655888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 39755888e44171ffd48b591d19256884a969fe4da17caryclark } 39855888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppStartT)) { 39955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppStartT=%g", glitch.fOppStartT); 40055888e44171ffd48b591d19256884a969fe4da17caryclark } 40155888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppEndT)) { 40255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndT=%g", glitch.fOppEndT); 40355888e44171ffd48b591d19256884a969fe4da17caryclark } 40455888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 40555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 40655888e44171ffd48b591d19256884a969fe4da17caryclark } 407ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DumpGlitchType(glitch.fType); 40855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("\n"); 40955888e44171ffd48b591d19256884a969fe4da17caryclark } 410ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 41155888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(false); 412ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 4136c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if 01 && DEBUG_ACTIVE_SPANS 414ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// SkDebugf("active after %s:\n", id); 41555888e44171ffd48b591d19256884a969fe4da17caryclark ShowActiveSpans(contourList); 41655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 41755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 41826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 41926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 4204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::DumpGlitchType(GlitchType glitchType) { 423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark switch (glitchType) { 424ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 426ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break; 428ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 430ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 431ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 432ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 433ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 434ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 435ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCorrectEnd_Glitch: SkDebugf(" CorrectEnd"); break; 438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 439ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 440ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kFail_Glitch: SkDebugf(" Fail"); break; 441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 443ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 444ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; 446ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 447ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 448ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 449ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 450ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 451ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 452ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 453ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 454ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 455ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 456ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 457ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReturnFalse_Glitch: SkDebugf(" ReturnFalse"); break; 458ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 459ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 461ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUninitialized_Glitch: break; 462ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark default: SkASSERT(0); 463ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 464ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 465ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 468570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 46907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 47007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 47107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 47207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 47307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 47407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 47507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 47607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 47707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 47807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 47907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 48007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 48107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 48207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 48307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 48407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 485570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 48607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 48707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 48807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 489570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 49007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 49107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 49207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 49307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 49407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 49507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 49654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 49754359294a7c9dc54802d512a5d891a35c1663392caryclark 498a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 49907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 500385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 501cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 502385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 503a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 504570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 50507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 50607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 50707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 50807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 50907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 51007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 51107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 51207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 51307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 51407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 51507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 51607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 51707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 518a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 519a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 520570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5211049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 5221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 5231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 5241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 5251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 5261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5281049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 5291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 5301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 5311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 53255888e44171ffd48b591d19256884a969fe4da17caryclark "kXOR_PathOp", 5331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 5341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 5351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 53603b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 53703b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 53803b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 53903b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 5401049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 5411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 5421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 5431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 545086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex); 5461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5471049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 5481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 5491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 5501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 5511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 5521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 5531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 5544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 55627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 55726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 55826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 55926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 562ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSK_DECLARE_STATIC_MUTEX(gCoinDictMutex); 563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToGlobalCoinDicts() { 565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkAutoMutexAcquire ac(&gCoinDictMutex); 566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict); 567ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict); 568ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 569ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 570ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 571ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 57526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 57626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 57726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 57826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 57926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 58026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 58126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 58426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 58526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 58626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 59626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 59726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 59826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 60026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 60126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 60226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 60326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 60526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 60626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 60826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 65427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 6551326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkOpGlobalState::DebugRunFail() { 6561326068147ee60de138061a3fc1157fcfd5d017bcaryclark return SkPathOpsDebug::gRunFail; 65727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 65827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this is const so it can be called by const methods that overwise don't alter state 660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE || DEBUG_COIN 661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const { 662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark auto writable = const_cast<SkOpGlobalState*>(this); 663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->setPhase(phase); 665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::CoinDictEntry* entry = &writable->fCoinDictEntry; 668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fPreviousFuncName = entry->fFunctionName; 669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fIteration = iteration; 670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fLineNumber = lineNo; 671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = SkPathOpsDebug::kUninitialized_Glitch; 672ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fFunctionName = funcName; 673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fCoinVisitedDict.add(*entry); 674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->debugAddToCoinChangedDict(); 675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 67926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 68026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 68226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 68326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 68426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 68526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 68626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 68726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 68826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 69126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 69226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 693a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark#include "SkPathOpsConic.h" 694624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 695624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 696624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 697624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 698624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 699624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 700624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 701624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 702624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 703624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 704624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 705624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 706624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 707624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 708a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDQuad::debugSet(const SkDPoint* pts) { 709a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 710a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 711a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 712a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 713a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDCubic::debugSet(const SkDPoint* pts) { 714a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 715a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 716a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 717a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 718a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDConic::debugSet(const SkDPoint* pts, SkScalar weight) { 719a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fPts.debugSet(pts); 720a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fWeight = weight; 721a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 722a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 723ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 724ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 725ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 726ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 7274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 728570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 729570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 730ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 73155888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT() 732ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* SkOpSegment::debugAddT(double t, SkPathOpsDebug::GlitchLog* log) const { 73355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 73455888e44171ffd48b591d19256884a969fe4da17caryclark SkPoint pt = this->ptAtT(t); 73555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* span = &fHead; 73626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 73755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* result = span->ptT(); 73829b2563afb1677515739f1d24fb27733626eca92caryclark if (t == result->fT || this->match(result, this, t, pt)) { 73955888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 740ef4f32ac858825dc443cfe4739ea878fb0bf550fcaryclark return result; 74155888e44171ffd48b591d19256884a969fe4da17caryclark } 74255888e44171ffd48b591d19256884a969fe4da17caryclark if (t < result->fT) { 74355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = result->span()->prev(); 74430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(!prev, span); 74529b2563afb1677515739f1d24fb27733626eca92caryclark // marks in global state that new op span has been allocated 74629b2563afb1677515739f1d24fb27733626eca92caryclark this->globalState()->setAllocatedOpSpan(); 74755888e44171ffd48b591d19256884a969fe4da17caryclark// span->init(this, prev, t, pt); 74855888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 74955888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 75055888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 75155888e44171ffd48b591d19256884a969fe4da17caryclark// span->segment()->debugID(), span->debugID()); 75255888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 75355888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 75455888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 75555888e44171ffd48b591d19256884a969fe4da17caryclark } 75630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(span != &fTail, span); 75755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->upCast()->next())); 75855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 75929b2563afb1677515739f1d24fb27733626eca92caryclark return nullptr; // we never get here, but need this to satisfy compiler 76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 76226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 76326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 76426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 76826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 76955888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 77126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 77326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 77755888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 784ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 786ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugCheckHealth(SkPathOpsDebug::GlitchLog* glitches) const { 787ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveMultiples(glitches); 788ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveNearby(glitches); 789ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMissingCoincidence(glitches); 79055888e44171ffd48b591d19256884a969fe4da17caryclark} 79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 79255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll() 793ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const { 79455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span = &fHead; 79555888e44171ffd48b591d19256884a969fe4da17caryclark do { 796ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugClearOne(span, glitches); 79755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->next()->upCastable())); 798ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->globalState()->coincidence()->debugRelease(glitches, this); 79926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 80155888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne() 802ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const { 803ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->windValue()) glitches->record(SkPathOpsDebug::kCollapsedWindValue_Glitch, span); 804ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->oppValue()) glitches->record(SkPathOpsDebug::kCollapsedOppValue_Glitch, span); 805ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span->done()) glitches->record(SkPathOpsDebug::kCollapsedDone_Glitch, span); 80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 80726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 80826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 80954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 81096fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 81154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 81254359294a7c9dc54802d512a5d891a35c1663392caryclark do { 81354359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 814dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 81554359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 816dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 81754359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 818dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 819dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 820dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 821dac1d17027dcaa5596885a9f333979418b35001ccaryclark 822ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 82355888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited 82455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 82555888e44171ffd48b591d19256884a969fe4da17caryclark // reset visited flag back to false 82655888e44171ffd48b591d19256884a969fe4da17caryclark do { 82755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 82855888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != stopPtT) { 82955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->segment(); 83055888e44171ffd48b591d19256884a969fe4da17caryclark opp->resetDebugVisited(); 83155888e44171ffd48b591d19256884a969fe4da17caryclark } 83255888e44171ffd48b591d19256884a969fe4da17caryclark } while (!span->final() && (span = span->upCast()->next())); 83355888e44171ffd48b591d19256884a969fe4da17caryclark} 83455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 83555888e44171ffd48b591d19256884a969fe4da17caryclark 836ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 83755888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence() 83855888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves 83955888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear 84055888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed 84155888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given 84255888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C: 84355888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 84455888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C. 84555888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2, 84655888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B. 847ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 84826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 84926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 85026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 85226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 85355888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 85426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 85526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 85626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 85726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 85826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 85926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->span()->segment(); 86226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 86655888e44171ffd48b591d19256884a969fe4da17caryclark if (!opp->debugVisited()) { 86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87255888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this) { 87355888e44171ffd48b591d19256884a969fe4da17caryclark continue; 87455888e44171ffd48b591d19256884a969fe4da17caryclark } 87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 87626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 87855888e44171ffd48b591d19256884a969fe4da17caryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88155888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88355888e44171ffd48b591d19256884a969fe4da17caryclark } 88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 88726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 88826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 88926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 894ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = priorPtT->span()->segment(); 89526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 89626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 89826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90655888e44171ffd48b591d19256884a969fe4da17caryclark if (priorPtT == ptT) { 90755888e44171ffd48b591d19256884a969fe4da17caryclark continue; 90855888e44171ffd48b591d19256884a969fe4da17caryclark } 90926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 91755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 91855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPtT = ptT->span()->ptT(); 91955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 92055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 92155888e44171ffd48b591d19256884a969fe4da17caryclark if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 92226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 92326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 92455888e44171ffd48b591d19256884a969fe4da17caryclark if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 92555888e44171ffd48b591d19256884a969fe4da17caryclark // mark coincidence 92630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE 92755888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 92855888e44171ffd48b591d19256884a969fe4da17caryclark// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 92955888e44171ffd48b591d19256884a969fe4da17caryclark// rootOppEnd->debugID()); 93055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 931ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMissingCoin_Glitch, priorPtT, ptT, oppStart, oppEnd); 93255888e44171ffd48b591d19256884a969fe4da17caryclark // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 93355888e44171ffd48b591d19256884a969fe4da17caryclark // } 93455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 935d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 93655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 93755888e44171ffd48b591d19256884a969fe4da17caryclark // result = true; 93826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 93926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 94026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 94126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 94226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 94326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 94426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 94555888e44171ffd48b591d19256884a969fe4da17caryclark DebugClearVisited(&fHead); 94655888e44171ffd48b591d19256884a969fe4da17caryclark return; 94726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 94826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 94955888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples() 95055888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed 951ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const { 95255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 95326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 95426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 95526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 95626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(addCount >= 1); 95726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (addCount == 1) { 95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 96126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 96526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 96626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 97126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 97226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 100426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 100526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 100726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 100826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 100926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 101026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 101226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 101326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 101426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 101526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 101626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 101726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 101826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 101926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 102126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 102226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 102326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 102426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 102626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 102726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 102855888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 1029ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugMergeMatches(glitches, oppSpan); 1030ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugAddOpp(glitches, oppSpan); 103155888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 103226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 103326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 103455888e44171ffd48b591d19256884a969fe4da17caryclark tryNextSpan: 103526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 103626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 103726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 103855888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan: 103926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 104026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 104155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 104255888e44171ffd48b591d19256884a969fe4da17caryclark return; 104326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 104426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 104555888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby() 104655888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1047ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const { 104855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 104955888e44171ffd48b591d19256884a969fe4da17caryclark // release undeleted spans pointing to this seg that are linked to the primary span 105055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* spanBase = &fHead; 105126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 105255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = spanBase->ptT(); 105355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* headPtT = ptT; 105455888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != headPtT) { 105555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = ptT->span(); 105655888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this && !ptT->deleted() && test != spanBase 105755888e44171ffd48b591d19256884a969fe4da17caryclark && test->ptT() == ptT) { 105855888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 105955888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase == &fHead) { 1060ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll_Glitch, this); 106155888e44171ffd48b591d19256884a969fe4da17caryclark// return; 106255888e44171ffd48b591d19256884a969fe4da17caryclark } 1063ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyReleaseFinal_Glitch, spanBase, ptT); 106455888e44171ffd48b591d19256884a969fe4da17caryclark } else if (test->prev()) { 1065ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyRelease_Glitch, test, headPtT); 106655888e44171ffd48b591d19256884a969fe4da17caryclark } 106755888e44171ffd48b591d19256884a969fe4da17caryclark// break; 106826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 106926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 107055888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = spanBase->upCast()->next(); 107155888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 107255888e44171ffd48b591d19256884a969fe4da17caryclark 107355888e44171ffd48b591d19256884a969fe4da17caryclark // This loop looks for adjacent spans which are near by 107455888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = &fHead; 107555888e44171ffd48b591d19256884a969fe4da17caryclark do { // iterate through all spans associated with start 107655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = spanBase->upCast()->next(); 107755888e44171ffd48b591d19256884a969fe4da17caryclark if (this->spansNearby(spanBase, test)) { 107855888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 107955888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->prev()) { 1080ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 108155888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1082ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll2_Glitch, this); 108355888e44171ffd48b591d19256884a969fe4da17caryclark // return 108455888e44171ffd48b591d19256884a969fe4da17caryclark } 108555888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1086ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMerge_Glitch, spanBase); 108755888e44171ffd48b591d19256884a969fe4da17caryclark } 108855888e44171ffd48b591d19256884a969fe4da17caryclark } 108955888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = test; 109055888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 109155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 109226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 109326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 109426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 10954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 10961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 10974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1099025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 1100025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const { 1101025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { 1102025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = index; 1103025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = SkTMin(t, fDebugBaseMin); 1104025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = SkTMax(t, fDebugBaseMax); 1105025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1106025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1107025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); 1108025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugLastMax < 0 || fDebugLastIndex == index) { 1109025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = index; 1110025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = SkTMin(t, fDebugLastMin); 1111025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = SkTMax(t, fDebugLastMax); 1112025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1113025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1114025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); 1115025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); 1116025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 1117025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 1118025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 111954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 11204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const { 11214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 11224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 11234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 11244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 11264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 112754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 112854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 112954359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 11304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 11334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 113654359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 11371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); 113855888e44171ffd48b591d19256884a969fe4da17caryclark // since endpoints may have be adjusted, show actual computed curves 113955888e44171ffd48b591d19256884a969fe4da17caryclark SkDCurve curvePart; 114055888e44171ffd48b591d19256884a969fe4da17caryclark this->subDivide(span, span->next(), &curvePart); 114155888e44171ffd48b591d19256884a969fe4da17caryclark const SkDPoint* pts = curvePart.fCubic.fPts; 114255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 11434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 114455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 11454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 114755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9gf", curvePart.fConic.fWeight); 11481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 114955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 115054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 1151624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=?"); 11524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1153624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=%d", span->windSum()); 1154624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1155624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 1156624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=?"); 1157624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1158624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=%d", span->oppSum()); 1159624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1160624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windValue=%d", span->windValue()); 1161624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 1162624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppValue=%d", span->oppValue()); 11634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 116454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 116554359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 11664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 11684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 116954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 117054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 117154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 11721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 11734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 11744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 11754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 11764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 117754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 117854359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 117954359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 11804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 11814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 118254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 11834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 118454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 118554359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 118654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 118754359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 118854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 118954359294a7c9dc54802d512a5d891a35c1663392caryclark } 119054359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 11914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 119354359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 11944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 119554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 11961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 11974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 11984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 11994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 12004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 120154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 120254359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 120354359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 120454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 120554359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 120654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 120754359294a7c9dc54802d512a5d891a35c1663392caryclark } 120854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 120954359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 121054359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 121154359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 121254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 121354359294a7c9dc54802d512a5d891a35c1663392caryclark } 121454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 121554359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 12164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 121854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 12194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 12204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 122154359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 12224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 122454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 12254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 122654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 12274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 122854359294a7c9dc54802d512a5d891a35c1663392caryclark 12294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 12304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 123126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 123226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 123326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 123455888e44171ffd48b591d19256884a969fe4da17caryclark This checks the distance between start points; the distance between 123526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 123626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 123726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 123826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 123926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 124026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 124126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 124226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 124326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 124426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 124526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 124626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 124726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 124826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 124926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 125326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 127255888e44171ffd48b591d19256884a969fe4da17caryclark } while (test->fNext != this); 127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 127654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 127754359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 127854359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 127954359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 128054359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 1281eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fPart.fCurve), 128254359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 128354359294a7c9dc54802d512a5d891a35c1663392caryclark break; 128454359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 1285eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fPart.fCurve), 128654359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 128754359294a7c9dc54802d512a5d891a35c1663392caryclark break; 12881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 12891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 1290eed356d281adbf93ecbd89cb23913a7861cd8578caryclark CONIC_DEBUG_DATA(fPart.fCurve, fPart.fCurve.fConic.fWeight), 12911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 12921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 129354359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 1294eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fPart.fCurve), 129554359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 129654359294a7c9dc54802d512a5d891a35c1663392caryclark break; 129754359294a7c9dc54802d512a5d891a35c1663392caryclark default: 129854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 12991b24933e52f50773de29332387a12721811f3012mtklein } 130054359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 130154359294a7c9dc54802d512a5d891a35c1663392caryclark} 130254359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 130354359294a7c9dc54802d512a5d891a35c1663392caryclark 1304624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 130554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 130654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 130754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 130854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 130954359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 131054359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 131154359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 131254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 131354359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 131454359294a7c9dc54802d512a5d891a35c1663392caryclark do { 131554359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 131654359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 131754359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 132154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 132255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 132355888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 132455888e44171ffd48b591d19256884a969fe4da17caryclark return; 132555888e44171ffd48b591d19256884a969fe4da17caryclark } 132655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 132754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 132854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 132954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 133054359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 133154359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 133254359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 133354359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 133454359294a7c9dc54802d512a5d891a35c1663392caryclark do { 133554359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 133654359294a7c9dc54802d512a5d891a35c1663392caryclark return; 133754359294a7c9dc54802d512a5d891a35c1663392caryclark } 133854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 133954359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 134054359294a7c9dc54802d512a5d891a35c1663392caryclark return; 134154359294a7c9dc54802d512a5d891a35c1663392caryclark } 134254359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 134354359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 134454359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 134554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 134654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 134754359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 134854359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 134954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 135054359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1351624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 135254359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 135354359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 135454359294a7c9dc54802d512a5d891a35c1663392caryclark } 135554359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 135654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 135754359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1358624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 135954359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 136054359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 136154359294a7c9dc54802d512a5d891a35c1663392caryclark } 136254359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 136354359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 13641326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail); 13651326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail); 136654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 136754359294a7c9dc54802d512a5d891a35c1663392caryclark} 136854359294a7c9dc54802d512a5d891a35c1663392caryclark 136954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 137054359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 137154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 137254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 137354359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 137454359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1375f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 137654359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 137754359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 137854359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 137954359294a7c9dc54802d512a5d891a35c1663392caryclark break; 138054359294a7c9dc54802d512a5d891a35c1663392caryclark } 1381f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 138254359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 138354359294a7c9dc54802d512a5d891a35c1663392caryclark return; 138454359294a7c9dc54802d512a5d891a35c1663392caryclark } 138554359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 138654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 138754359294a7c9dc54802d512a5d891a35c1663392caryclark} 138854359294a7c9dc54802d512a5d891a35c1663392caryclark 138955888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG 139055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 139155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpGlobalState* debugState) const { 13921326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail()); 13931326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail()); 139455888e44171ffd48b591d19256884a969fe4da17caryclark} 139555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 139626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1397ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 1398ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// sets the span's end to the ptT referenced by the previous-next 1399ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log, 1400ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, 1401ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) const ) const { 1402ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* origPtT = (this->*getEnd)(); 1403ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* origSpan = origPtT->span(); 1404ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = origSpan->prev(); 1405ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = prev ? prev->next()->ptT() 1406ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : origSpan->upCast()->next()->prev()->ptT(); 1407ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (origPtT != testPtT) { 1408ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCorrectEnd_Glitch, this, origPtT, testPtT); 1409ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1410ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1411ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1412ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1413ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* Commented-out lines keep this in sync with correctEnds */ 1414ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// FIXME: member pointers have fallen out of favor and can be replaced with 1415ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// an alternative approach. 1416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// makes all span ends agree with the segment's spans that define them 1417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 1418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTStart, nullptr); 1419ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTEnd, nullptr); 1420ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTStart, nullptr); 1421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTEnd, nullptr); 1422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 142455888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */ 142530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// expand the range by checking adjacent spans for coincidence 1426ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkCoincidentSpans::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 142755888e44171ffd48b591d19256884a969fe4da17caryclark bool expanded = false; 142855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = coinPtTStart()->segment(); 142955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSegment = oppPtTStart()->segment(); 143055888e44171ffd48b591d19256884a969fe4da17caryclark do { 143155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coinPtTStart()->span()->upCast(); 143255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = start->prev(); 143355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 143455888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev || !(oppPtT = prev->contains(oppSegment))) { 143555888e44171ffd48b591d19256884a969fe4da17caryclark break; 143655888e44171ffd48b591d19256884a969fe4da17caryclark } 143755888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (prev->t() + start->t()) / 2; 143855888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 143955888e44171ffd48b591d19256884a969fe4da17caryclark break; 144055888e44171ffd48b591d19256884a969fe4da17caryclark } 1441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, prev->ptT(), oppPtT); 144255888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 144355888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 144455888e44171ffd48b591d19256884a969fe4da17caryclark do { 144555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coinPtTEnd()->span(); 144655888e44171ffd48b591d19256884a969fe4da17caryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 144730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (next && next->deleted()) { 144830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 144930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 145055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 145155888e44171ffd48b591d19256884a969fe4da17caryclark if (!next || !(oppPtT = next->contains(oppSegment))) { 145255888e44171ffd48b591d19256884a969fe4da17caryclark break; 145355888e44171ffd48b591d19256884a969fe4da17caryclark } 145455888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (end->t() + next->t()) / 2; 145555888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 145655888e44171ffd48b591d19256884a969fe4da17caryclark break; 145755888e44171ffd48b591d19256884a969fe4da17caryclark } 1458ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, next->ptT(), oppPtT); 145955888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 146055888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 146155888e44171ffd48b591d19256884a969fe4da17caryclark return expanded; 146255888e44171ffd48b591d19256884a969fe4da17caryclark} 146355888e44171ffd48b591d19256884a969fe4da17caryclark 1464ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1465ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* base, const SkOpSpanBase* testSpan) const { 1466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = testSpan->ptT(); 1467ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* stopPtT = testPtT; 1468ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* baseSeg = base->segment(); 1469ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark while ((testPtT = testPtT->next()) != stopPtT) { 1470ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* testSeg = testPtT->segment(); 1471ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->deleted()) { 1472ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1474ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testSeg == baseSeg) { 1475ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1476ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1477ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->span()->ptT() != testPtT) { 1478ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1479ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1480ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->contains(baseSeg, testSeg, testPtT->fT)) { 1481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1482ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1483ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // intersect perp with base->ptT() with testPtT->segment() 1484ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDVector dxdy = baseSeg->dSlopeAtT(base->t()); 1485ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkPoint& pt = base->pt(); 1486ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}}; 1487ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkIntersections i; 1488ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i); 1489ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < i.used(); ++index) { 1490ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double t = i[0][index]; 1491ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!between(0, t, 1)) { 1492ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1493ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1494ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDPoint oppPt = i.pt(index); 1495ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oppPt.approximatelyEqual(pt)) { 1496ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1497ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1498ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg); 1499ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPtT* oppStart = writableSeg->addT(t); 1500ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart == testPtT) { 1501ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1502ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1503ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSpan* writableBase = const_cast<SkOpSpan*>(base); 1504ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppStart->span()->addOpp(writableBase); 1505ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart->deleted()) { 1506ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1507ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1508ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* coinSeg = base->segment(); 1509ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* oppSeg = oppStart->segment(); 1510ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double coinTs, coinTe, oppTs, oppTe; 1511ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (Ordered(coinSeg, oppSeg)) { 1512ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = base->t(); 1513ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testSpan->t(); 1514ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = oppStart->fT; 1515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testPtT->fT; 1516ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1517ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinSeg, oppSeg); 1518ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = oppStart->fT; 1519ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testPtT->fT; 1520ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = base->t(); 1521ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testSpan->t(); 1522ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1523ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coinTs > coinTe) { 1524ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinTs, coinTe); 1525ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(oppTs, oppTe); 1526ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1527ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 1528ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added), false) { 1529ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1530ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1531ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1532ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1533ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1534ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1535ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1536ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1537ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* ptT) const { 1538ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!ptT->span()->upCastable(), ptT->span()); 1539ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* base = ptT->span()->upCast(); 1540ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = base->prev(); 1541ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!prev, ptT->span()); 1542ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!prev->isCanceled()) { 1543ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->prev()), false) { 1544ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1545ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1546ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1547ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!base->isCanceled()) { 1548ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->next()), false) { 1549ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1550ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1551ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1552ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1553ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1554ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1555ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* If A is coincident with B and B includes an endpoint, and A's matching point 1556ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark is not the endpoint (i.e., there's an implied line connecting B-end and A) 1557ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark then assume that the same implied line may intersect another curve close to B. 1558ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark Since we only care about coincidence that was undetected, look at the 1559ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but 1560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark next door) and see if the A matching point is close enough to form another 1561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincident pair. If so, check for a new coincident span between B-end/A ptT loop 1562ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark and the adjacent ptT loop. 1563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark*/ 1564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const { 1565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* span = fHead; 1566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span) { 1567ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1568ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1569ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fTop = span; 1570ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fHead = nullptr; 1571ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1572ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) { 1573ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(1 == span->coinPtTStart()->fT, span); 1574ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTStart()->fT == 0; 1575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTStart()->fT); 1576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1577ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { // if both are on end, any nearby intersect was already found 1578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTStart()), false) { 1579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTStart()), false) { 1584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1587ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1588ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) { 1589ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTEnd()->fT == 1; 1590ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT); 1591ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1592ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { 1593ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTEnd()), false) { 1594ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1595ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1596ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1597ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1598ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTEnd()), false) { 1599ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1600ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1601ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1602ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1603ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((span = span->next())); 1604ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this->restoreHead(); 1605ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1606ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1607ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 160855888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */ 160955888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans 161055888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 1611ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddExpanded(SkPathOpsDebug::GlitchLog* log) const { 1612a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark// DEBUG_SET_PHASE(); 161326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 161426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 1615ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1616ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 161726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 161855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* startPtT = coin->coinPtTStart(); 161955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oStartPtT = coin->oppPtTStart(); 1620ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double priorT = startPtT->fT; 1621ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double oPriorT = oStartPtT->fT; 1622ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(startPtT->contains(oStartPtT), coin); 1623ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 162426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 162526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 162655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 162755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 162830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(oEnd->deleted(), coin); 162930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!start->upCastable(), coin); 163026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 1631ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->flipped() && !oStart->upCastable(), coin); 163255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 1633ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 1634ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* seg = start->segment(); 1635ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* oSeg = oStart->segment(); 163626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 1637ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedOpp = test->ptT()->contains(oSeg); 1638ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedThis = oTest->ptT()->contains(seg); 1639ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!containedOpp || !containedThis) { 1640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // choose the ends, or the first common pt-t list shared by both 1641ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double nextT, oNextT; 1642ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (containedOpp) { 1643ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = test->t(); 1644ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = containedOpp->fT; 1645ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (containedThis) { 1646ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = containedThis->fT; 1647ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = oTest->t(); 1648ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1649ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // iterate through until a pt-t list found that contains the other 1650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* walk = test; 1651ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* walkOpp; 1652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!walk->upCastable(), coin); 1654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark walk = walk->upCast()->next(); 1655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (!(walkOpp = walk->ptT()->contains(oSeg)) 1656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark && walk != coin->coinPtTEnd()->span()); 1657a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!walkOpp, coin); 1658ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = walk->t(); 1659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = walkOpp->fT; 1660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 166126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 1662a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startRange = nextT - priorT; 166330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!startRange, coin); 1664a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startPart = (test->t() - priorT) / startRange; 1665a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double oStartRange = oNextT - oPriorT; 166630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!oStartRange, coin); 166726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 166830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(startPart == oStartPart, coin); 1669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart 1670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : !!containedThis; 167155888e44171ffd48b591d19256884a969fe4da17caryclark bool startOver = false; 1672ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark addToOpp ? log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT + oStartRange * startPart, test) 1674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT + startRange * oStartPart, oTest); 1676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // FAIL_IF(!success, coin); 167755888e44171ffd48b591d19256884a969fe4da17caryclark if (startOver) { 167855888e44171ffd48b591d19256884a969fe4da17caryclark test = start; 167955888e44171ffd48b591d19256884a969fe4da17caryclark oTest = oStart; 168026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1681ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end = coin->coinPtTEnd()->span(); 1682ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oEnd = coin->oppPtTEnd()->span(); 168326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168455888e44171ffd48b591d19256884a969fe4da17caryclark if (test != end) { 1685ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!test->upCastable(), coin); 1686ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT = test->t(); 168726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168955888e44171ffd48b591d19256884a969fe4da17caryclark if (oTest != oEnd) { 1690ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT = oTest->t(); 169155888e44171ffd48b591d19256884a969fe4da17caryclark oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 1692ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 169326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 169655888e44171ffd48b591d19256884a969fe4da17caryclark return; 169755888e44171ffd48b591d19256884a969fe4da17caryclark} 169855888e44171ffd48b591d19256884a969fe4da17caryclark 169955888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */ 17008016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// note that over1s, over1e, over2s, over2e are ordered 1701ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddIfMissing(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s, 170281a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added, 17038016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* over1e, const SkOpPtT* over2e) const { 17048016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(tStart < tEnd); 17058016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->fT < over1e->fT); 17068016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tStart, over1e->fT)); 17078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 17088016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->fT < over2e->fT); 17098016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tStart, over2e->fT)); 17108016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 17118016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over1e->segment()); 17128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->segment() == over2e->segment()); 17138016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over2s->segment()); 17148016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != coinSeg); 17158016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != oppSeg); 17168016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(coinSeg != oppSeg); 171726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 17188016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 17198016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 17208016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinSeg->collapsed(coinTs, coinTe)) { 1721ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, coinSeg); 172226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17238016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 17248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 17258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (oppSeg->collapsed(oppTs, oppTe)) { 1726ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, oppSeg); 172726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinTs > coinTe) { 17298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkTSwap(coinTs, coinTe); 173026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 173126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1732ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added 17338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ); 173455888e44171ffd48b591d19256884a969fe4da17caryclark} 173555888e44171ffd48b591d19256884a969fe4da17caryclark 173655888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */ 173730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 173830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 1739ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log, 174030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 174181a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double coinTs, double coinTe, double oppTs, double oppTe, bool* added) const { 174255888e44171ffd48b591d19256884a969fe4da17caryclark SkTDArray<SkCoincidentSpans*> overlaps; 1743ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(!fTop); // this is (correctly) reversed in addifMissing() 174481a478ca6c36aac3e53ce0373a281ac8940f4780caryclark if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, 174581a478ca6c36aac3e53ce0373a281ac8940f4780caryclark &overlaps)) { 174655888e44171ffd48b591d19256884a969fe4da17caryclark return; 174755888e44171ffd48b591d19256884a969fe4da17caryclark } 174855888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 174955888e44171ffd48b591d19256884a969fe4da17caryclark coinTe, oppTs, oppTe, &overlaps)) { 175055888e44171ffd48b591d19256884a969fe4da17caryclark return; 175155888e44171ffd48b591d19256884a969fe4da17caryclark } 175255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 175355888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 175455888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = overlaps[index]; 175555888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 1756ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTStart()); 175755888e44171ffd48b591d19256884a969fe4da17caryclark } 175855888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 1759ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTEnd()); 176055888e44171ffd48b591d19256884a969fe4da17caryclark } 176155888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 176255888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 176355888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 1764ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTStart()); 176555888e44171ffd48b591d19256884a969fe4da17caryclark } 176655888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 176755888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 176855888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 1769ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTEnd()); 177055888e44171ffd48b591d19256884a969fe4da17caryclark } 1771ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!fHead) { this->debugRelease(log, fHead, test); 1772ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, fTop, test); 177355888e44171ffd48b591d19256884a969fe4da17caryclark } 177455888e44171ffd48b591d19256884a969fe4da17caryclark } 177555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 177655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 177730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); 177830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(cs != ce || !cs, coinSeg); 177955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 178055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 178130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); 178255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !cs || !cs->deleted()); 178355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !os || !os->deleted()); 178455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !ce || !ce->deleted()); 178555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !oe || !oe->deleted()); 178655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 178755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 178830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); 178930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && (csExisting == ce || 179030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); 179130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceExisting && (ceExisting == cs || 179230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); 179355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 179455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 179530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); 179630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && (osExisting == oe || 179730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); 179830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeExisting && (oeExisting == os || 179930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oeExisting->contains(osExisting ? osExisting : os)), oppSeg); 180055888e44171ffd48b591d19256884a969fe4da17caryclark bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 180155888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 180255888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !os) { 180355888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs) 1804ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark cs = coinSeg->debugAddT(coinTs, log); 180555888e44171ffd48b591d19256884a969fe4da17caryclark if (!os) 1806ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark os = oppSeg->debugAddT(oppTs, log); 180730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 1808ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (cs && os) cs->span()->debugAddOpp(log, os->span()); 180955888e44171ffd48b591d19256884a969fe4da17caryclark// cs = csWritable; 181030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// os = osWritable->active(); 181130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg); 181255888e44171ffd48b591d19256884a969fe4da17caryclark } 181355888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce || !oe) { 181455888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce) 1815ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ce = coinSeg->debugAddT(coinTe, log); 181655888e44171ffd48b591d19256884a969fe4da17caryclark if (!oe) 1817ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oe = oppSeg->debugAddT(oppTe, log); 1818ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ce && oe) ce->span()->debugAddOpp(log, oe->span()); 181955888e44171ffd48b591d19256884a969fe4da17caryclark// ce = ceWritable; 182055888e44171ffd48b591d19256884a969fe4da17caryclark// oe = oeWritable; 182155888e44171ffd48b591d19256884a969fe4da17caryclark } 182255888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 182330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csDeleted, coinSeg); 182430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osDeleted, oppSeg); 182530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceDeleted, coinSeg); 182630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeDeleted, oppSeg); 18278016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg); 18288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark bool result = true; 182955888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap) { 183055888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->segment() == coinSeg) { 1831ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 183255888e44171ffd48b591d19256884a969fe4da17caryclark } else { 183355888e44171ffd48b591d19256884a969fe4da17caryclark if (oppTs > oppTe) { 183455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 183555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(oppTs, oppTe); 183655888e44171ffd48b591d19256884a969fe4da17caryclark } 1837ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 183855888e44171ffd48b591d19256884a969fe4da17caryclark } 18398016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (result) { 18418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark overlap->debugShow(); 18428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark } 184355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 184455888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1845ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingCoin_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 18468016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18478016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark fHead->debugShow(); 184855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 184955888e44171ffd48b591d19256884a969fe4da17caryclark } 185055888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 18518016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return (void) result; 185226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 185326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 185455888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing() 185555888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */ 185655888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */ 185755888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again 1858ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddMissing(SkPathOpsDebug::GlitchLog* log, bool* added) const { 185926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 1860ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *added = false; 186126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 186226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 186326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 186455888e44171ffd48b591d19256884a969fe4da17caryclark // fTop = outer; 186555888e44171ffd48b591d19256884a969fe4da17caryclark // fHead = nullptr; 186626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 186726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 186826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 186926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 18708016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ocs = outer->coinPtTStart(); 18718016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ocs->deleted()); 18728016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerCoin = ocs->segment(); 18738016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 18748016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oos = outer->oppPtTStart(); 1875ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oos->deleted()) { 1876ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1877ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 18788016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerOpp = oos->segment(); 18798016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerOpp->done()); 18808016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 18818016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 188226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 188355888e44171ffd48b591d19256884a969fe4da17caryclark while ((inner = inner->next())) { 188455888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 188526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 18868016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ics = inner->coinPtTStart(); 18878016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ics->deleted()); 18888016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerCoin = ics->segment(); 18898016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerCoin->done()); 18908016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ios = inner->oppPtTStart(); 18918016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ios->deleted()); 18928016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerOpp = ios->segment(); 18938016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerOpp->done()); 18948016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin); 18958016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 189655888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin == innerCoin) { 18978016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 1898ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oce->deleted()) { 1899ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1900ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 19018016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19028016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 19038016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) { 1904ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ics->starter(ice), 190581a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerOpp, added, 19068016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 190826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 190955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerCoin == innerOpp) { 19108016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 19118016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!oce->deleted()); 19128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 19138016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ioe->deleted()); 19148016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) { 1915ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ios->starter(ioe), 191681a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerCoin, added, 19178016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19188016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 191926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 192055888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerCoin) { 19218016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19238016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 192555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerOpp); 19268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 1927ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ics->starter(ice), 192881a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerOpp, added, 19298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 193126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 193255888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerOpp) { 19338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19348016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19358016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 1936ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ioe->deleted()) { 1937ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1938ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 193955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerCoin); 19408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 1941ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ios->starter(ioe), 194281a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerCoin, added, 19438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19448016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 194526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 194626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 194755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 194855888e44171ffd48b591d19256884a969fe4da17caryclark } 194955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((outer = outer->next())); 195055888e44171ffd48b591d19256884a969fe4da17caryclark // this->restoreHead(); 195155888e44171ffd48b591d19256884a969fe4da17caryclark return; 195255888e44171ffd48b591d19256884a969fe4da17caryclark} 195355888e44171ffd48b591d19256884a969fe4da17caryclark 195455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release() 1955ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { 195630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 195730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* prev = nullptr; 195830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* next; 195930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 196030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark next = coin->next(); 196130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (coin == remove) { 196230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (prev) { 196330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// prev->setNext(next); 196430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else if (head == fHead) { 196530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fHead = next; 196630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 196730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fTop = next; 196830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 1969ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 197030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 197130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark prev = coin; 197230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((coin = next)); 197330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 197430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 197530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 1976ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 197755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 197855888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 197955888e44171ffd48b591d19256884a969fe4da17caryclark return; 198055888e44171ffd48b591d19256884a969fe4da17caryclark } 198155888e44171ffd48b591d19256884a969fe4da17caryclark do { 198255888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->segment() == deleted 198355888e44171ffd48b591d19256884a969fe4da17caryclark || coin->coinPtTEnd()->segment() == deleted 198455888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTStart()->segment() == deleted 198555888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTEnd()->segment() == deleted) { 1986ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 198730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 198855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 198926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 199026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 199155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand() 199255888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence 1993ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkOpCoincidence::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 199426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 199526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 199626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 199726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 199826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 199926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2000ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coin->debugExpand(log)) { 200155888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if multiple spans expanded so they are now identical 200255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = fHead; 200355888e44171ffd48b591d19256884a969fe4da17caryclark do { 200455888e44171ffd48b591d19256884a969fe4da17caryclark if (coin == test) { 200555888e44171ffd48b591d19256884a969fe4da17caryclark continue; 200655888e44171ffd48b591d19256884a969fe4da17caryclark } 200755888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == test->coinPtTStart() 200855888e44171ffd48b591d19256884a969fe4da17caryclark && coin->oppPtTStart() == test->oppPtTStart()) { 2009ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, fHead, test->coinPtTStart()); 201055888e44171ffd48b591d19256884a969fe4da17caryclark break; 201155888e44171ffd48b591d19256884a969fe4da17caryclark } 201255888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next())); 201355888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 201426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 201555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 201626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 201726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 201826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 201955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark() 202055888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 2021ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMark(SkPathOpsDebug::GlitchLog* log) const { 202226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 202326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 202426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 202526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 202626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2027ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable(), coin); 202855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 202955888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(start->deleted()); 203055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 203155888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(end->deleted()); 203255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 203355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oStart->deleted()); 203455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 203555888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oEnd->deleted()); 203655888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 203726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 203826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 203926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 204055888e44171ffd48b591d19256884a969fe4da17caryclark /* coin and opp spans may not match up. Mark the ends, and then let the interior 204155888e44171ffd48b591d19256884a969fe4da17caryclark get marked as many times as the spans allow */ 2042ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark start->debugInsertCoincidence(log, oStart->upCast()); 2043ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end->debugInsertCoinEnd(log, oEnd); 204455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = start->segment(); 204555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oSegment = oStart->segment(); 204626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 204726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 2048a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark bool ordered; 2049a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!coin->ordered(&ordered), coin); 205055888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->upCast()->next()) != end) { 2051ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!next->upCastable(), coin); 2052ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (next->upCast()->debugInsertCoincidence(log, oSegment, flipped, ordered), false) { 205355888e44171ffd48b591d19256884a969fe4da17caryclark return; 205426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 205555888e44171ffd48b591d19256884a969fe4da17caryclark } 205655888e44171ffd48b591d19256884a969fe4da17caryclark while ((oNext = oNext->upCast()->next()) != oEnd) { 2057ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oNext->upCastable(), coin); 2058ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oNext->upCast()->debugInsertCoincidence(log, segment, flipped, ordered), false) { 205955888e44171ffd48b591d19256884a969fe4da17caryclark return; 206026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 206155888e44171ffd48b591d19256884a969fe4da17caryclark } 206255888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 206355888e44171ffd48b591d19256884a969fe4da17caryclark return; 206455888e44171ffd48b591d19256884a969fe4da17caryclark} 206555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 206655888e44171ffd48b591d19256884a969fe4da17caryclark 2067ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 206855888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2069ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 207030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 207155888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 207255888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->collapsed(test)) { 207355888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 2074ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 207526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 207655888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 2077ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 207855888e44171ffd48b591d19256884a969fe4da17caryclark } 2079ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, head, coin); 208055888e44171ffd48b591d19256884a969fe4da17caryclark } 208155888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 208255888e44171ffd48b591d19256884a969fe4da17caryclark } 208355888e44171ffd48b591d19256884a969fe4da17caryclark} 208455888e44171ffd48b591d19256884a969fe4da17caryclark 208555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2086ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 2087ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fHead, test); 2088ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fTop, test); 208926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 209026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 209126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 209255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const { 20936c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(), 209455888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->fT, coinPtTEnd()->fT); 20956c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(), 209655888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->fT, oppPtTEnd()->fT); 209755888e44171ffd48b591d19256884a969fe4da17caryclark} 209855888e44171ffd48b591d19256884a969fe4da17caryclark 2099624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 210055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 210155888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* span = fHead; 2102624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 210355888e44171ffd48b591d19256884a969fe4da17caryclark span->debugShow(); 210455888e44171ffd48b591d19256884a969fe4da17caryclark span = span->next(); 2105624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 210655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2107624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2108624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 2109ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 21106c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end, 211155888e44171ffd48b591d19256884a969fe4da17caryclark double oStart, double oEnd, const SkOpSegment* oSegment, 2112ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 211355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(next != end); 211455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!next->contains(end) || log); 211555888e44171ffd48b591d19256884a969fe4da17caryclark if (next->t() > end->t()) { 211655888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(next, end); 211755888e44171ffd48b591d19256884a969fe4da17caryclark } 211855888e44171ffd48b591d19256884a969fe4da17caryclark do { 211955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = next->ptT(); 212055888e44171ffd48b591d19256884a969fe4da17caryclark int index = 0; 212127c015dfcf4e2b8fb1abe327cc40204e2a4f452acaryclark bool somethingBetween = false; 212255888e44171ffd48b591d19256884a969fe4da17caryclark do { 212355888e44171ffd48b591d19256884a969fe4da17caryclark ++index; 212455888e44171ffd48b591d19256884a969fe4da17caryclark ptT = ptT->next(); 212555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* checkPtT = next->ptT(); 212655888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT == checkPtT) { 212755888e44171ffd48b591d19256884a969fe4da17caryclark break; 212855888e44171ffd48b591d19256884a969fe4da17caryclark } 212955888e44171ffd48b591d19256884a969fe4da17caryclark bool looped = false; 213055888e44171ffd48b591d19256884a969fe4da17caryclark for (int check = 0; check < index; ++check) { 213155888e44171ffd48b591d19256884a969fe4da17caryclark if ((looped = checkPtT == ptT)) { 213255888e44171ffd48b591d19256884a969fe4da17caryclark break; 213355888e44171ffd48b591d19256884a969fe4da17caryclark } 213455888e44171ffd48b591d19256884a969fe4da17caryclark checkPtT = checkPtT->next(); 213555888e44171ffd48b591d19256884a969fe4da17caryclark } 213655888e44171ffd48b591d19256884a969fe4da17caryclark if (looped) { 213755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 213855888e44171ffd48b591d19256884a969fe4da17caryclark break; 213955888e44171ffd48b591d19256884a969fe4da17caryclark } 214055888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->deleted()) { 214155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 214255888e44171ffd48b591d19256884a969fe4da17caryclark } 214355888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() != oSegment) { 214455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 214555888e44171ffd48b591d19256884a969fe4da17caryclark } 214655888e44171ffd48b591d19256884a969fe4da17caryclark somethingBetween |= between(oStart, ptT->fT, oEnd); 214755888e44171ffd48b591d19256884a969fe4da17caryclark } while (true); 214855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(somethingBetween); 214955888e44171ffd48b591d19256884a969fe4da17caryclark } while (next != end && (next = next->upCast()->next())); 215055888e44171ffd48b591d19256884a969fe4da17caryclark} 215155888e44171ffd48b591d19256884a969fe4da17caryclark 215255888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 2153ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 215455888e44171ffd48b591d19256884a969fe4da17caryclark if (!list) { 215555888e44171ffd48b591d19256884a969fe4da17caryclark return; 215655888e44171ffd48b591d19256884a969fe4da17caryclark } 215755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 215855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 215955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 216055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 216155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg != test->oppPtTStart()->segment()); 216255888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 216355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tcs, 1)); 216455888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 216555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tce, 1)); 216655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tcs < tce); 216755888e44171ffd48b591d19256884a969fe4da17caryclark double tos = test->oppPtTStart()->fT; 216855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tos, 1)); 216955888e44171ffd48b591d19256884a969fe4da17caryclark double toe = test->oppPtTEnd()->fT; 217055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, toe, 1)); 217155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tos != toe); 217255888e44171ffd48b591d19256884a969fe4da17caryclark if (tos > toe) { 217355888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(tos, toe); 217455888e44171ffd48b591d19256884a969fe4da17caryclark } 217555888e44171ffd48b591d19256884a969fe4da17caryclark do { 217655888e44171ffd48b591d19256884a969fe4da17caryclark double lcs, lce, los, loe; 217755888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == list->coinPtTStart()->segment()) { 217855888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->oppPtTStart()->segment()) { 217955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 218055888e44171ffd48b591d19256884a969fe4da17caryclark } 218155888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->coinPtTStart()->fT; 218255888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->coinPtTEnd()->fT; 218355888e44171ffd48b591d19256884a969fe4da17caryclark los = list->oppPtTStart()->fT; 218455888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->oppPtTEnd()->fT; 218555888e44171ffd48b591d19256884a969fe4da17caryclark if (los > loe) { 218655888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(los, loe); 218755888e44171ffd48b591d19256884a969fe4da17caryclark } 218855888e44171ffd48b591d19256884a969fe4da17caryclark } else if (coinSeg == list->oppPtTStart()->segment()) { 218955888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->coinPtTStart()->segment()) { 219055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 219155888e44171ffd48b591d19256884a969fe4da17caryclark } 219255888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->oppPtTStart()->fT; 219355888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->oppPtTEnd()->fT; 219455888e44171ffd48b591d19256884a969fe4da17caryclark if (lcs > lce) { 219555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(lcs, lce); 219655888e44171ffd48b591d19256884a969fe4da17caryclark } 219755888e44171ffd48b591d19256884a969fe4da17caryclark los = list->coinPtTStart()->fT; 219855888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->coinPtTEnd()->fT; 219955888e44171ffd48b591d19256884a969fe4da17caryclark } else { 220055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 220155888e44171ffd48b591d19256884a969fe4da17caryclark } 220255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tce < lcs || lce < tcs); 220355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(toe < los || loe < tos); 220455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((list = list->next())); 220555888e44171ffd48b591d19256884a969fe4da17caryclark} 220655888e44171ffd48b591d19256884a969fe4da17caryclark 220755888e44171ffd48b591d19256884a969fe4da17caryclark 220855888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2209ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 221055888e44171ffd48b591d19256884a969fe4da17caryclark // check for overlapping coincident spans 221155888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = head; 221255888e44171ffd48b591d19256884a969fe4da17caryclark while (test) { 221355888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* next = test->next(); 2214ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, next, log); 2215ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, opt, log); 221655888e44171ffd48b591d19256884a969fe4da17caryclark test = next; 221755888e44171ffd48b591d19256884a969fe4da17caryclark } 221855888e44171ffd48b591d19256884a969fe4da17caryclark} 221955888e44171ffd48b591d19256884a969fe4da17caryclark 222055888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2221ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 222255888e44171ffd48b591d19256884a969fe4da17caryclark // look for pts inside coincident spans that are not inside the opposite spans 222355888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = head; 222455888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 222555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 222655888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->segment())); 222755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 222855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 222955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 223055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 22316c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark coin = coin->next(); 22326c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 22346c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22356c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22366c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 22376c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugValidate() const { 22386c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if DEBUG_COINCIDENCE 2239ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, nullptr); 2240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, nullptr); 22416c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22426c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22436c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 2244ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 22456c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2246ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 22476c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark // look for pts inside coincident spans that are not inside the opposite spans 22486c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark const SkCoincidentSpans* coin = head; 22496c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark while (coin) { 22506c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 225155888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 2252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 22536c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 225455888e44171ffd48b591d19256884a969fe4da17caryclark coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 2255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 225655888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 225755888e44171ffd48b591d19256884a969fe4da17caryclark } 2258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 225955888e44171ffd48b591d19256884a969fe4da17caryclark} 226055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 226155888e44171ffd48b591d19256884a969fe4da17caryclark 22626c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugCheckBetween() const { 226355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 22646c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark if (fGlobalState->debugCheckHealth()) { 22656c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark return; 22666c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fHead, fTop, nullptr); 2268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fTop, nullptr, nullptr); 226955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 227055888e44171ffd48b591d19256884a969fe4da17caryclark} 227155888e44171ffd48b591d19256884a969fe4da17caryclark 2272ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugCheckHealth(SkPathOpsDebug::GlitchLog* log) const { 2274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugCheckHealth(log); 2277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 227855888e44171ffd48b591d19256884a969fe4da17caryclark} 2279ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2280ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCheckValid(SkPathOpsDebug::GlitchLog* log) const { 2281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 2282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, log); 2283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, log); 228455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2285ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 228655888e44171ffd48b591d19256884a969fe4da17caryclark 2287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 2288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* coin = fHead; 2289ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!coin) { 2290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 229226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coin->debugCorrectEnds(log); 2294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((coin = coin->next())); 229526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 229626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 229755888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence() 2298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 229955888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fCount > 0); 230026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 230155888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 230226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2303e47ae2998c1cf944db5743a416583dd0f042b6d9Cary Clark if (segment->debugMissingCoincidence(log), false) { 230455888e44171ffd48b591d19256884a969fe4da17caryclark// result = true; 230555888e44171ffd48b591d19256884a969fe4da17caryclark } 230655888e44171ffd48b591d19256884a969fe4da17caryclark segment = segment->next(); 230755888e44171ffd48b591d19256884a969fe4da17caryclark } while (segment); 230855888e44171ffd48b591d19256884a969fe4da17caryclark return; 230926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 2310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveMultiples(SkPathOpsDebug::GlitchLog* log) const { 2312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (segment->debugMoveMultiples(log), false) { 2316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2318ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2319ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2320ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 2321ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2322ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const { 2323ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2324ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2325ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2326ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugMoveNearby(log); 2327ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2328ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 232926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 233026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2331025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2332025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugResetCoinT() const { 2333025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = -1; 2334025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = 1; 2335025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = -1; 2336025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = -1; 2337025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = 1; 2338025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = -1; 2339025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2340025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2341025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 23424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 2343025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2344025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark { 2345025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpSpanBase* span = &fHead; 2346025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2347025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugResetCoinT(); 2348025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2349025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span = &fHead; 2350025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark int index = 0; 2351025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2352025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugSetCoinT(index++); 2353025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2354025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2355025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 235655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 235755888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 235855888e44171ffd48b591d19256884a969fe4da17caryclark return; 235955888e44171ffd48b591d19256884a969fe4da17caryclark } 236055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 23614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 236254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 236354359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 236496fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 236554359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 23664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 236754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 236854359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 236954359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 237054359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 237154359294a7c9dc54802d512a5d891a35c1663392caryclark } 237254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 237354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 237454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 237554359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 237654359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 237754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 237854359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 237954359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 238054359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 238154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 238254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 238308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 238454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 238554359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 238654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 238754359294a7c9dc54802d512a5d891a35c1663392caryclark} 238854359294a7c9dc54802d512a5d891a35c1663392caryclark 2389ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 239030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 239130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with addOpp() 2392ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugAddOpp(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 239330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 239430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!oppPrev) { 239555888e44171ffd48b591d19256884a969fe4da17caryclark return; 239626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2397ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMergeMatches(log, opp); 239830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->ptT()->debugAddOpp(opp->ptT(), oppPrev); 2399ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 240026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 240126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 240255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 2403ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* log) const { 240455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coins = this->globalState()->coincidence(); 240555888e44171ffd48b591d19256884a969fe4da17caryclark if (coins->isEmpty()) { 240655888e44171ffd48b591d19256884a969fe4da17caryclark return; 240755888e44171ffd48b591d19256884a969fe4da17caryclark } 240855888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span 240955888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop 241055888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span 241155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 241255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* test = head; 241326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 241455888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->coincident()) { 241555888e44171ffd48b591d19256884a969fe4da17caryclark continue; 241626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coins->debugMarkCollapsed(log, test); 241855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next()) != head); 241926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 242055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 242126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 242254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 242354359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 242454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 242554359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 242654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 242754359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 242854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 242954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 243054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 243154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 243254359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 243354359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 243454359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 243554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 243654359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 243754359294a7c9dc54802d512a5d891a35c1663392caryclark } 243854359294a7c9dc54802d512a5d891a35c1663392caryclark } 243954359294a7c9dc54802d512a5d891a35c1663392caryclark } 244054359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 244154359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 244254359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 244354359294a7c9dc54802d512a5d891a35c1663392caryclark} 244454359294a7c9dc54802d512a5d891a35c1663392caryclark 2445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 244655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd() 2447ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 244855888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoinEnd(coin)) { 244955888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoinEnd(this)); 245055888e44171ffd48b591d19256884a969fe4da17caryclark return; 245155888e44171ffd48b591d19256884a969fe4da17caryclark } 245255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 245355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2454ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinEnd_Glitch, this, coin); 245555888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoinEnd = this->fCoinEnd; 245655888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoinEnd = coinNext; 245755888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 245855888e44171ffd48b591d19256884a969fe4da17caryclark} 245955888e44171ffd48b591d19256884a969fe4da17caryclark 246030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with mergeMatches() 246130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Look to see if pt-t linked list contains same segment more than once 246230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if so, and if each pt-t is directly pointed to by spans in that segment, 246330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// merge them 246430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// keep the points, but remove spans so that the segment doesn't have 2 or more 246530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// spans pointing to the same pt-t loop at different loop elements 2466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugMergeMatches(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 246730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* test = &fPtT; 246830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* testNext; 246930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* stop = test; 247030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 247130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark testNext = test->next(); 247230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (test->deleted()) { 247330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 247430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 247530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* testBase = test->span(); 247630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(testBase->ptT() == test); 247730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* segment = test->segment(); 247830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (segment->done()) { 247930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 248030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 248130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* inner = opp->ptT(); 248230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* innerStop = inner; 248330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 248430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->segment() != segment) { 248530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 248630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 248730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->deleted()) { 248830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 248930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 249030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* innerBase = inner->span(); 249130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(innerBase->ptT() == inner); 249230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // when the intersection is first detected, the span base is marked if there are 249330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // more than one point in the intersection. 249430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) { 249530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(inner->fT)) { 2496ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, innerBase, test); 249730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 249830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(inner->fT != test->fT); 249930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(test->fT)) { 2500ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, testBase, inner); 250130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 2502ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, segment); 250330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(testBase->debugSetDeleted()); 250430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// test->setDeleted(); 250530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(innerBase->debugSetDeleted()); 250630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// inner->setDeleted(); 250730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#ifdef SK_DEBUG // assert if another undeleted entry points to segment 251030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* debugInner = inner; 251130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark while ((debugInner = debugInner->next()) != innerStop) { 251230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->segment() != segment) { 251330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 251430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 251530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->deleted()) { 251630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 251730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 251830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkOPASSERT(0); 251930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 252030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#endif 252130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 252230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// } 252330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 252430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((inner = inner->next()) != innerStop); 252530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((test = testNext) != stop); 2526ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 252730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 252830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 252955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 253026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2531025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugResetCoinT() const { 2532025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2533025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2534025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2535025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugResetCoinT(); 2536025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2537025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2538025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2539025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2540025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2541025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugSetCoinT(int index) const { 2542025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2543025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2544025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2545025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (!ptT->deleted()) { 2546025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugSetCoinT(index); 2547025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2548025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2549025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2550025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2551025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2552025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 255326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 255426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 255526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 255626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 255726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 255826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 255926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 256026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 256126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 256226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 256326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 256426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 256526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 256654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 256755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 256855888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 256955888e44171ffd48b591d19256884a969fe4da17caryclark return; 257055888e44171ffd48b591d19256884a969fe4da17caryclark } 257155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 257254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 257354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 257454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 257554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 257654359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 257754359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 257854359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 257954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 258054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 258154359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 258254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 258354359294a7c9dc54802d512a5d891a35c1663392caryclark } 258454359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 258554359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 258654359294a7c9dc54802d512a5d891a35c1663392caryclark } 258754359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 258854359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 258954359294a7c9dc54802d512a5d891a35c1663392caryclark } 25904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 259154359294a7c9dc54802d512a5d891a35c1663392caryclark} 259254359294a7c9dc54802d512a5d891a35c1663392caryclark 259354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 259454359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 259554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 259654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 259754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 259854359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 259954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 260054359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 260154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 260254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 260354359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 260454359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 260554359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 260654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 260754359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 260854359294a7c9dc54802d512a5d891a35c1663392caryclark } 260954359294a7c9dc54802d512a5d891a35c1663392caryclark } 261054359294a7c9dc54802d512a5d891a35c1663392caryclark } 261154359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 261254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 261354359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 261454359294a7c9dc54802d512a5d891a35c1663392caryclark} 261554359294a7c9dc54802d512a5d891a35c1663392caryclark 2616ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 261755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header 2618ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 261955888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoincidence(coin)) { 262055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoincidence(this)); 262155888e44171ffd48b591d19256884a969fe4da17caryclark return; 262255888e44171ffd48b591d19256884a969fe4da17caryclark } 262355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 262455888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2625ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinStart_Glitch, this, coin); 262655888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoincident = this->fCoincident; 262755888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoincident = coinNext; 262855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 262955888e44171ffd48b591d19256884a969fe4da17caryclark} 263055888e44171ffd48b591d19256884a969fe4da17caryclark 263155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() 2632ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped, bool ordered) const { 263355888e44171ffd48b591d19256884a969fe4da17caryclark if (this->containsCoincidence(segment)) { 263455888e44171ffd48b591d19256884a969fe4da17caryclark return; 263555888e44171ffd48b591d19256884a969fe4da17caryclark } 263655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* next = &fPtT; 263755888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->next()) != &fPtT) { 263855888e44171ffd48b591d19256884a969fe4da17caryclark if (next->segment() == segment) { 2639ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* span; 2640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* base = next->span(); 2641ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!ordered) { 2642ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* spanEnd = fNext->contains(segment)->span(); 2643ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT()); 2644ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!start->span()->upCastable(), this); 2645ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = const_cast<SkOpSpan*>(start->span()->upCast()); 2646ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2647ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else if (flipped) { 2648ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->prev(); 2649ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!span, this); 2650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2651ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else { 2652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!base->upCastable(), this); 2653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->upCast(); 2654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2655ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinInsert_Glitch, span); 265655888e44171ffd48b591d19256884a969fe4da17caryclark return; 265755888e44171ffd48b591d19256884a969fe4da17caryclark } 265855888e44171ffd48b591d19256884a969fe4da17caryclark } 2659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinMissing_Glitch, segment, this); 266155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 266355888e44171ffd48b591d19256884a969fe4da17caryclark} 266455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 266555888e44171ffd48b591d19256884a969fe4da17caryclark 2666624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 2667624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 2668624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 2669624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 2670624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 2671624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2672624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 2673624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 2674624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 2675624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 2676624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 2677624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2678624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 2679624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 2680624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 2681624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2682624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 2683624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2684624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 2685624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 2686624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2687624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 268854359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 268954359294a7c9dc54802d512a5d891a35c1663392caryclark 269055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp() 269129b2563afb1677515739f1d24fb27733626eca92caryclarkvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { 269229b2563afb1677515739f1d24fb27733626eca92caryclark SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); 269355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(this != opp); 269455888e44171ffd48b591d19256884a969fe4da17caryclark// this->fNext = opp; 269529b2563afb1677515739f1d24fb27733626eca92caryclark SkASSERT(oppPrev != oldNext); 269655888e44171ffd48b591d19256884a969fe4da17caryclark// oppPrev->fNext = oldNext; 269755888e44171ffd48b591d19256884a969fe4da17caryclark} 269855888e44171ffd48b591d19256884a969fe4da17caryclark 269926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 270026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 270126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 270226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 270326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 270426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 270526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 270626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 270726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 270826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 270926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 271026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 271126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 271226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 271326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 271426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 271526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 271626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 271726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 271826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 271926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 272026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 272126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 272226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 272326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 272426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 272526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 272626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 272726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 272826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 272926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 273026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 273126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 273226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 273326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 273526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 273726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 273826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 27398016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclarkconst SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const { 27408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return fT < end->fT ? end : this; 27418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark} 27428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark 274354359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 274454359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 274554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 274654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 274754359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 274854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 274954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 275054359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 275154359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 275254359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 275354359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 275454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 275554359294a7c9dc54802d512a5d891a35c1663392caryclark } 275654359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 275754359294a7c9dc54802d512a5d891a35c1663392caryclark } 27584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 27594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 276026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 276126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 276226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 276326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 276426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 276526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 276626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 276754359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 276854359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 276954359294a7c9dc54802d512a5d891a35c1663392caryclark} 277054359294a7c9dc54802d512a5d891a35c1663392caryclark 277129b2563afb1677515739f1d24fb27733626eca92caryclarkconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { 277229b2563afb1677515739f1d24fb27733626eca92caryclark return this->oppPrev(const_cast<SkOpPtT*>(opp)); 277329b2563afb1677515739f1d24fb27733626eca92caryclark} 277429b2563afb1677515739f1d24fb27733626eca92caryclark 2775025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugResetCoinT() const { 2776025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2777025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugResetCoinT(); 2778025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2779025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2780025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2781025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugSetCoinT(int index) const { 2782025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2783025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugSetCoinT(index, fT); 2784025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2785025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2786025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 278754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 278855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 278955888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 279055888e44171ffd48b591d19256884a969fe4da17caryclark return; 279155888e44171ffd48b591d19256884a969fe4da17caryclark } 279255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 279354359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 2794ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPhase phase = contour()->globalState()->phase(); 2795ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (phase == SkOpPhase::kIntersecting || phase == SkOpPhase::kFixWinding) { 279654359294a7c9dc54802d512a5d891a35c1663392caryclark return; 27974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 279854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 279954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 280054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 280154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 28024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 28034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 28041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28051049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 28061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 28071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 28081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 28091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 28101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 28111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 28121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 28131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 28141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 28151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 28171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 28181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28211049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 28221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 28231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 28241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 28261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 28271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28321049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 28331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 28341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 28351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 28361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 28371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 28381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 28391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 28401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 28421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 28431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 28441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 28451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 28481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 28491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 28531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 28541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 28561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 28581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 28591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 28601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 28631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 28641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 28661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 28671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 28681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28721049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 28731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 28741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 28751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 28761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 28771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 28781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28791049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 28801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 28811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 28821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 288396fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 28841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 28851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 28861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 28871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 28881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 28891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 28901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 28911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 28921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 28931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 28941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 28951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 28971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 28991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 29001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 29011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 29021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 29031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 29041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 29051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 29061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 29071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 29081326068147ee60de138061a3fc1157fcfd5d017bcaryclark 2909918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY 29101326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkData.h" 29111326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkStream.h" 29121326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29131326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) { 29141326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDynamicMemoryWStream wStream; 29151326068147ee60de138061a3fc1157fcfd5d017bcaryclark path.dump(&wStream, force, dumpAsHex); 29161326068147ee60de138061a3fc1157fcfd5d017bcaryclark sk_sp<SkData> data(wStream.detachAsData()); 29171326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data()); 29181326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29191326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29201326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int dumpID = 0; 29211326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29221326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(const SkPath& one, const SkPath& two, SkPathOp op, 29231326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* testName) { 29241326068147ee60de138061a3fc1157fcfd5d017bcaryclark FILE* file = sk_fopen("op_dump.txt", kWrite_SkFILE_Flag); 29251326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(file, one, two, op, testName); 29261326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29271326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29281326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op, 29291326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* testName) { 29301326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* name = testName ? testName : "op"; 29311326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, 29321326068147ee60de138061a3fc1157fcfd5d017bcaryclark "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 29331326068147ee60de138061a3fc1157fcfd5d017bcaryclark name, ++dumpID); 29341326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path;\n"); 29351326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType()); 29361326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, one, false, true); 29371326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path1(path);\n"); 29381326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.reset();\n"); 29391326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType()); 29401326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, two, false, true); 29411326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path2(path);\n"); 29421326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op); 29431326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "}\n\n"); 29441326068147ee60de138061a3fc1157fcfd5d017bcaryclark fclose(file); 29451326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29461326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29471326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(const SkPath& path, const char* testName) { 29481326068147ee60de138061a3fc1157fcfd5d017bcaryclark FILE* file = sk_fopen("simplify_dump.txt", kWrite_SkFILE_Flag); 29491326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(file, path, testName); 29501326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29511326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29521326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(FILE* file, const SkPath& path, const char* testName) { 29531326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* name = testName ? testName : "simplify"; 29541326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, 29551326068147ee60de138061a3fc1157fcfd5d017bcaryclark "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 29561326068147ee60de138061a3fc1157fcfd5d017bcaryclark name, ++dumpID); 29571326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path;\n"); 29581326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", path.getFillType()); 29591326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, path, false, true); 29601326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " testSimplify(reporter, path, filename);\n"); 29611326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "}\n\n"); 29621326068147ee60de138061a3fc1157fcfd5d017bcaryclark fclose(file); 29631326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29641326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29651326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkBitmap.h" 29661326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkCanvas.h" 29671326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkPaint.h" 29681326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29691326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitWidth = 64; 29701326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitHeight = 64; 29711326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29721326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void debug_scale_matrix(const SkPath& one, const SkPath* two, SkMatrix& scale) { 29731326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRect larger = one.getBounds(); 29741326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (two) { 29751326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.join(two->getBounds()); 29761326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 29771326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar largerWidth = larger.width(); 29781326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (largerWidth < 4) { 29791326068147ee60de138061a3fc1157fcfd5d017bcaryclark largerWidth = 4; 29801326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 29811326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar largerHeight = larger.height(); 29821326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (largerHeight < 4) { 29831326068147ee60de138061a3fc1157fcfd5d017bcaryclark largerHeight = 4; 29841326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 29851326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar hScale = (bitWidth - 2) / largerWidth; 29861326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar vScale = (bitHeight - 2) / largerHeight; 29871326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.reset(); 29881326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.preScale(hScale, vScale); 29891326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fLeft *= hScale; 29901326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fRight *= hScale; 29911326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fTop *= vScale; 29921326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fBottom *= vScale; 29931326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft 29941326068147ee60de138061a3fc1157fcfd5d017bcaryclark : 16000 < larger.fRight ? 16000 - larger.fRight : 0; 29951326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop 29961326068147ee60de138061a3fc1157fcfd5d017bcaryclark : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0; 29971326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.preTranslate(dx, dy); 29981326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29991326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30001326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) { 30011326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (bits.width() == 0) { 30021326068147ee60de138061a3fc1157fcfd5d017bcaryclark bits.allocN32Pixels(bitWidth * 2, bitHeight); 30031326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30041326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkCanvas canvas(bits); 30051326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawColor(SK_ColorWHITE); 30061326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPaint paint; 30071326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.save(); 30081326068147ee60de138061a3fc1157fcfd5d017bcaryclark const SkRect& bounds1 = one.getBounds(); 30091326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); 30101326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawPath(one, paint); 30111326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.restore(); 30121326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.save(); 30131326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1); 30141326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawPath(two, paint); 30151326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.restore(); 30161326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = 0; 30171326068147ee60de138061a3fc1157fcfd5d017bcaryclark for (int y = 0; y < bitHeight - 1; ++y) { 30181326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr1 = bits.getAddr32(0, y); 30191326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr2 = bits.getAddr32(0, y + 1); 30201326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr3 = bits.getAddr32(bitWidth, y); 30211326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1); 30221326068147ee60de138061a3fc1157fcfd5d017bcaryclark for (int x = 0; x < bitWidth - 1; ++x) { 30231326068147ee60de138061a3fc1157fcfd5d017bcaryclark // count 2x2 blocks 30241326068147ee60de138061a3fc1157fcfd5d017bcaryclark bool err = addr1[x] != addr3[x]; 30251326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (err) { 30261326068147ee60de138061a3fc1157fcfd5d017bcaryclark errors += addr1[x + 1] != addr3[x + 1] 30271326068147ee60de138061a3fc1157fcfd5d017bcaryclark && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1]; 30281326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30291326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30301326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30311326068147ee60de138061a3fc1157fcfd5d017bcaryclark return errors; 30321326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30331326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30341326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op) { 30351326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDebugf("// Op did not expect failure\n"); 30361326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(stderr, one, two, op, "opTest"); 30371326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30381326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30391326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30401326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op, 30411326068147ee60de138061a3fc1157fcfd5d017bcaryclark const SkPath& result) { 30421326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath pathOut, scaledPathOut; 30431326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion rgnA, rgnB, openClip, rgnOut; 30441326068147ee60de138061a3fc1157fcfd5d017bcaryclark openClip.setRect(-16000, -16000, 16000, 16000); 30451326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnA.setPath(one, openClip); 30461326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnB.setPath(two, openClip); 30471326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.op(rgnA, rgnB, (SkRegion::Op) op); 30481326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.getBoundaryPath(&pathOut); 30491326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkMatrix scale; 30501326068147ee60de138061a3fc1157fcfd5d017bcaryclark debug_scale_matrix(one, &two, scale); 30511326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; 30521326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledA, scaledB; 30531326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.addPath(one, scale); 30541326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.setFillType(one.getFillType()); 30551326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledB.addPath(two, scale); 30561326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledB.setFillType(two.getFillType()); 30571326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.setPath(scaledA, openClip); 30581326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnB.setPath(scaledB, openClip); 30591326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op); 30601326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnOut.getBoundaryPath(&scaledPathOut); 30611326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkBitmap bitmap; 30621326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledOut; 30631326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.addPath(result, scale); 30641326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.setFillType(result.getFillType()); 30651326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 30661326068147ee60de138061a3fc1157fcfd5d017bcaryclark const int MAX_ERRORS = 9; 30671326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (errors > MAX_ERRORS) { 30681326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(stderr, "// Op did not expect errors=%d\n", errors); 30691326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(stderr, one, two, op, "opTest"); 30701326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30711326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30721326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30731326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30741326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportSimplifyFail(const SkPath& path) { 30751326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDebugf("// Simplify did not expect failure\n"); 30761326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(stderr, path, "simplifyTest"); 30771326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30781326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30791326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30801326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) { 30811326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath pathOut, scaledPathOut; 30821326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion rgnA, openClip, rgnOut; 30831326068147ee60de138061a3fc1157fcfd5d017bcaryclark openClip.setRect(-16000, -16000, 16000, 16000); 30841326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnA.setPath(path, openClip); 30851326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.getBoundaryPath(&pathOut); 30861326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkMatrix scale; 30871326068147ee60de138061a3fc1157fcfd5d017bcaryclark debug_scale_matrix(path, nullptr, scale); 30881326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion scaledRgnA; 30891326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledA; 30901326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.addPath(path, scale); 30911326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.setFillType(path.getFillType()); 30921326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.setPath(scaledA, openClip); 30931326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.getBoundaryPath(&scaledPathOut); 30941326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkBitmap bitmap; 30951326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledOut; 30961326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.addPath(result, scale); 30971326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.setFillType(result.getFillType()); 30981326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 30991326068147ee60de138061a3fc1157fcfd5d017bcaryclark const int MAX_ERRORS = 9; 31001326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (errors > MAX_ERRORS) { 31011326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(stderr, "// Simplify did not expect errors=%d\n", errors); 31021326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(stderr, path, "simplifyTest"); 31031326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 31041326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 31051326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 31061326068147ee60de138061a3fc1157fcfd5d017bcaryclark 31071326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif 3108