107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc. 307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * 407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file. 607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h" 926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h" 1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h" 111326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkOSFile.h" 1202802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h" 131b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h" 1454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h" 1554359294a7c9dc54802d512a5d891a35c1663392caryclark 16918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY 171326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gDumpOp; // set to true to write op to file before a crash 181326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVerifyOp; // set to true to compare result against regions 191326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif 201326068147ee60de138061a3fc1157fcfd5d017bcaryclark 2159d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clarkbool SkPathOpsDebug::gRunFail; // set to true to check for success on tests known to fail 221326068147ee60de138061a3fc1157fcfd5d017bcaryclarkbool SkPathOpsDebug::gVeryVerbose; // set to true to run extensive checking tests 231326068147ee60de138061a3fc1157fcfd5d017bcaryclark 2430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_IF 2530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_IF(cond, coin) \ 26ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false) 2730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_WITH_NULL_IF 2930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_WITH_NULL_IF(cond, span) \ 30ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, span); } while (false) 3130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 3230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef RETURN_FALSE_IF 3330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define RETURN_FALSE_IF(cond, span) \ 34ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { if (cond) log->record(SkPathOpsDebug::kReturnFalse_Glitch, span); \ 35ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (false) 3630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 3755888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans; 3826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 39624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 40624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 41624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 42624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 43624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 44624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 45624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 46624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 47624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 50570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 52fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 53fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 54570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 5654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 5854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 66ff11428526843d3e03feb6843bd21f2d80536415Cary Clark 67ff11428526843d3e03feb6843bd21f2d80536415Cary Clark#if DEBUG_ACTIVE_SPANS 68ff11428526843d3e03feb6843bd21f2d80536415Cary ClarkSkString SkPathOpsDebug::gActiveSpans; 69ff11428526843d3e03feb6843bd21f2d80536415Cary Clark#endif 7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 71ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 73ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumChangedDict; 74ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumVisitedDict; 75ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 76ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic const int kGlitchType_Count = SkPathOpsDebug::kUnalignedTail_Glitch + 1; 7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 7826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 7926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 8026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 8255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* fOppSegment; 8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 8755888e44171ffd48b591d19256884a969fe4da17caryclark double fStartT; 8855888e44171ffd48b591d19256884a969fe4da17caryclark double fEndT; 8955888e44171ffd48b591d19256884a969fe4da17caryclark double fOppStartT; 9055888e44171ffd48b591d19256884a969fe4da17caryclark double fOppEndT; 9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 92ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchType fType; 93ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 94ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void dumpType() const; 9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 98ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void init(const SkOpGlobalState* state) { 99ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fGlobalState = state; 100ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 101ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 102ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* recordCommon(GlitchType type) { 10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 10755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = nullptr; 10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 11255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = SK_ScalarNaN; 11355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = SK_ScalarNaN; 11455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = SK_ScalarNaN; 11555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = SK_ScalarNaN; 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 11926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 121ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 123ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 128ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 12955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 130ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 13155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 13255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = ptT; 13355888e44171ffd48b591d19256884a969fe4da17caryclark } 13455888e44171ffd48b591d19256884a969fe4da17caryclark 135ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 13655888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* opp = NULL) { 137ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 13855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 13955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 14055888e44171ffd48b591d19256884a969fe4da17caryclark if (opp) { 14155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = opp->coinPtTStart(); 14255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = opp->coinPtTEnd(); 14355888e44171ffd48b591d19256884a969fe4da17caryclark } 14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 146ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, 14726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 148ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 15155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 155ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSpanBase* base, double t, 15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 157ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 15955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 163ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 165ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 16655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 16755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 16955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = coinSpan; 17055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = endSpan; 17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 173ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 17455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* base) { 175ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 17655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 17755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 17855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 181ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 183ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 190ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, double startT, 19155888e44171ffd48b591d19256884a969fe4da17caryclark double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 192ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 19355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 19455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = startT; 19555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = endT; 19655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = oppSeg; 19755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = oppStartT; 19855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = oppEndT; 19955888e44171ffd48b591d19256884a969fe4da17caryclark } 20055888e44171ffd48b591d19256884a969fe4da17caryclark 201ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg, 20255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span) { 203ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 20455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 20555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 20655888e44171ffd48b591d19256884a969fe4da17caryclark } 20755888e44171ffd48b591d19256884a969fe4da17caryclark 208ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, double t, const SkOpSpanBase* span) { 209ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 21055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 21155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 21255888e44171ffd48b591d19256884a969fe4da17caryclark } 21355888e44171ffd48b591d19256884a969fe4da17caryclark 214ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkOpSegment* seg) { 215ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 21655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 21755888e44171ffd48b591d19256884a969fe4da17caryclark } 21855888e44171ffd48b591d19256884a969fe4da17caryclark 219ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void record(GlitchType type, const SkCoincidentSpans* coin, 22055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 221ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SpanGlitch* glitch = recordCommon(type); 22255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 22355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = ptT; 22455888e44171ffd48b591d19256884a969fe4da17caryclark } 22555888e44171ffd48b591d19256884a969fe4da17caryclark 22626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 227ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpGlobalState* fGlobalState; 22826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 229ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 230ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 231ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const SkPathOpsDebug::CoinDict& dict) { 232ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = dict.fDict.count(); 233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->add(dict.fDict[index]); 235ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 236ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 237ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 238ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CoinDict::add(const CoinDictEntry& key) { 239ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark int count = fDict.count(); 240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < count; ++index) { 241ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark CoinDictEntry* entry = &fDict[index]; 242ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fIteration == key.fIteration && entry->fLineNumber == key.fLineNumber) { 243ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(!strcmp(entry->fFunctionName, key.fFunctionName)); 244ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (entry->fGlitchType == kUninitialized_Glitch) { 245ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = key.fGlitchType; 246ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 247ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 248ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 249ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 250ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *fDict.append() = key; 251ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 253ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 254ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 255ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 256ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void missing_coincidence(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 257ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // bool result = false; 259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 260ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark /* result |= */ contour->debugMissingCoincidence(glitches); 261ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 262ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 263ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 264ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 265ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_multiples(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 266ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 267ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 268ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (contour->debugMoveMultiples(glitches), false) { 269ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 270ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 271ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 272ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 273ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 275ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkstatic void move_nearby(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 276ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpContour* contour = contourList; 277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 278ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMoveNearby(glitches); 279ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((contour = contour->next())); 280ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 281ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 282ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 283ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 284ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 285ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToCoinChangedDict() { 287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 288ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 289e6522ea38fa3bcfdf2d718ea5ad898b3b3d46e00caryclark SkPathOpsDebug::CheckHealth(fContourHead); 290ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // see if next coincident operation makes a change; if so, record it 292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog glitches; 293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const char* funcName = fCoinDictEntry.fFunctionName; 294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!strcmp("calc_angles", funcName)) { 295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("missing_coincidence", funcName)) { 297ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark missing_coincidence(&glitches, fContourHead); 298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_multiples", funcName)) { 299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_multiples(&glitches, fContourHead); 300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("move_nearby", funcName)) { 301ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark move_nearby(&glitches, fContourHead); 302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addExpanded", funcName)) { 303ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddExpanded(&glitches); 304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addMissing", funcName)) { 305ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddMissing(&glitches, &added); 307ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("addEndMovedSpans", funcName)) { 308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugAddEndMovedSpans(&glitches); 309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("correctEnds", funcName)) { 310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugCorrectEnds(&glitches); 311ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("expand", funcName)) { 312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugExpand(&glitches); 313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("findOverlaps", funcName)) { 314ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 315ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("mark", funcName)) { 316ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoincidence->debugMark(&glitches); 317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (!strcmp("apply", funcName)) { 318ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ; 319ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 320ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(0); // add missing case 321ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 322ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (glitches.fGlitches.count()) { 323ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinDictEntry.fGlitchType = glitches.fGlitches[0].fType; 324ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 325ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark fCoinChangedDict.add(fCoinDictEntry); 326ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 32755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 32826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 32955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 33055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 331ff11428526843d3e03feb6843bd21f2d80536415Cary Clark SkString str; 33255888e44171ffd48b591d19256884a969fe4da17caryclark SkOpContour* contour = contourList; 33355888e44171ffd48b591d19256884a969fe4da17caryclark do { 334ff11428526843d3e03feb6843bd21f2d80536415Cary Clark contour->debugShowActiveSpans(&str); 33555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((contour = contour->next())); 336ff11428526843d3e03feb6843bd21f2d80536415Cary Clark if (!gActiveSpans.equals(str)) { 337ff11428526843d3e03feb6843bd21f2d80536415Cary Clark const char* s = str.c_str(); 338ff11428526843d3e03feb6843bd21f2d80536415Cary Clark const char* end; 339ff11428526843d3e03feb6843bd21f2d80536415Cary Clark while ((end = strchr(s, '\n'))) { 340ff11428526843d3e03feb6843bd21f2d80536415Cary Clark SkDebugf("%.*s", end - s + 1, s); 341ff11428526843d3e03feb6843bd21f2d80536415Cary Clark s = end + 1; 342ff11428526843d3e03feb6843bd21f2d80536415Cary Clark } 343ff11428526843d3e03feb6843bd21f2d80536415Cary Clark gActiveSpans.set(str); 344ff11428526843d3e03feb6843bd21f2d80536415Cary Clark } 34555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 34655888e44171ffd48b591d19256884a969fe4da17caryclark} 34755888e44171ffd48b591d19256884a969fe4da17caryclark 348ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE || DEBUG_COIN 349ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList) { 35055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 35155888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(true); 352ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 353ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 35626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 357ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugCheckValid(&glitches); // don't call validate; spans may be inconsistent 35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 359ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugCheckHealth(&glitches); 360ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark contour->debugMissingCoincidence(&glitches); 36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 36281a478ca6c36aac3e53ce0373a281ac8940f4780caryclark bool added; 363ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddMissing(&glitches, &added); 364ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugExpand(&glitches); 365ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugAddExpanded(&glitches); 366ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincidence->debugMark(&glitches); 36726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 36826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 36926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 37026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 37126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 37226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 37326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 37426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 375ff11428526843d3e03feb6843bd21f2d80536415Cary Clark SkDebugf(" %s\n", contourList->globalState()->debugCoinDictEntry().fFunctionName); 37655888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 37755888e44171ffd48b591d19256884a969fe4da17caryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 37855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%02d: ", index); 37955888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fBase) { 3808016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(), 3818016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fBase->debugID()); 38255888e44171ffd48b591d19256884a969fe4da17caryclark } 38355888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSuspect) { 3848016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(), 3858016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fSuspect->debugID()); 38655888e44171ffd48b591d19256884a969fe4da17caryclark } 38755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSegment) { 38855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fSegment->debugID()); 38955888e44171ffd48b591d19256884a969fe4da17caryclark } 39055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fCoinSpan) { 3918016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(), 3928016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID()); 39355888e44171ffd48b591d19256884a969fe4da17caryclark } 39455888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fEndSpan) { 39555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 39655888e44171ffd48b591d19256884a969fe4da17caryclark } 39755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSpan) { 3988016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(), 3998016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID()); 40055888e44171ffd48b591d19256884a969fe4da17caryclark } 40155888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppEndSpan) { 40255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 40355888e44171ffd48b591d19256884a969fe4da17caryclark } 40455888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fStartT)) { 40555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" startT=%g", glitch.fStartT); 40655888e44171ffd48b591d19256884a969fe4da17caryclark } 40755888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fEndT)) { 40855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endT=%g", glitch.fEndT); 40955888e44171ffd48b591d19256884a969fe4da17caryclark } 41055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSegment) { 41155888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 41255888e44171ffd48b591d19256884a969fe4da17caryclark } 41355888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppStartT)) { 41455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppStartT=%g", glitch.fOppStartT); 41555888e44171ffd48b591d19256884a969fe4da17caryclark } 41655888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppEndT)) { 41755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndT=%g", glitch.fOppEndT); 41855888e44171ffd48b591d19256884a969fe4da17caryclark } 41955888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 42055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 42155888e44171ffd48b591d19256884a969fe4da17caryclark } 422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DumpGlitchType(glitch.fType); 42355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("\n"); 42455888e44171ffd48b591d19256884a969fe4da17caryclark } 425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COINCIDENCE 42655888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(false); 427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 4286c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if 01 && DEBUG_ACTIVE_SPANS 429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// SkDebugf("active after %s:\n", id); 43055888e44171ffd48b591d19256884a969fe4da17caryclark ShowActiveSpans(contourList); 43155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 43255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 43326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 43426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 4354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkPathOpsDebug::DumpGlitchType(GlitchType glitchType) { 438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark switch (glitchType) { 439ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 440ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break; 443ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 444ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 446ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 447ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 448ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 449ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 450ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 451ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 452ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kCorrectEnd_Glitch: SkDebugf(" CorrectEnd"); break; 453ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 454ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 455ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kFail_Glitch: SkDebugf(" Fail"); break; 456ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 457ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 458ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 459ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; 461ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 462ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 463ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 464ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 465ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 467ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 468ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 469ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 470ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 471ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 472ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kReturnFalse_Glitch: SkDebugf(" ReturnFalse"); break; 473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 474ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 475ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 476ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark case kUninitialized_Glitch: break; 477ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark default: SkASSERT(0); 478ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 479ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 480ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 481ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 483570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 48407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 48507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 48607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 48707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 48807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 48907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 49007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 49107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 49207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 49307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 49407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 49507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 49607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 49707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 49807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 49907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 500570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 50107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 50207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 50307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 504570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 50507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 50607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 50707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 50807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 50907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 51007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 51154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 51254359294a7c9dc54802d512a5d891a35c1663392caryclark 513a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 51407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 515385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 516cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 517385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 518a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 519570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 52007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 52107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 52207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 52307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 52407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 52507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 52607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 52707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 52807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 52907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 53007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 53107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 53207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 533a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 534a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 535570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 5361049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 5371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 5381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 5391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 5401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 5411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5431049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 5441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 5451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 5461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 54755888e44171ffd48b591d19256884a969fe4da17caryclark "kXOR_PathOp", 5481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 5491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 5501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 55103b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 55203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 55303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 55403b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 5551049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 5561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 5571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 5581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 5591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 560086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex); 5611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 5621049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 5631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 5641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 5651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 5661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 5671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 5681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 5694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 57127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 577ab87d7abf1df007c90bef2e916294ca325d81c81Cary ClarkSK_DECLARE_STATIC_MUTEX(gCoinDictMutex); 578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugAddToGlobalCoinDicts() { 580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkAutoMutexAcquire ac(&gCoinDictMutex); 581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict); 582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict); 583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 59626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 59726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 59826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 59926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 60026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 60126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 60226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 60326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 60526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 60826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 65926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 66726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 66927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 67059d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clarkbool SkOpGlobalState::DebugRunFail() { 67159d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark return SkPathOpsDebug::gRunFail; 67259d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark} 67359d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark 674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this is const so it can be called by const methods that overwise don't alter state 675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE || DEBUG_COIN 676ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpGlobalState::debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const { 677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark auto writable = const_cast<SkOpGlobalState*>(this); 678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 679ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->setPhase(phase); 680ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 681ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 682ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::CoinDictEntry* entry = &writable->fCoinDictEntry; 683ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fPreviousFuncName = entry->fFunctionName; 684ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fIteration = iteration; 685ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fLineNumber = lineNo; 686ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fGlitchType = SkPathOpsDebug::kUninitialized_Glitch; 687ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark entry->fFunctionName = funcName; 688ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->fCoinVisitedDict.add(*entry); 689ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark writable->debugAddToCoinChangedDict(); 690ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 691ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 692ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#endif 693ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 69426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 69526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 69926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 70026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 70126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 70226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 70326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 70426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 70526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 70626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 70726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 708a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark#include "SkPathOpsConic.h" 709624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 710624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 711624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 712624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 713624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 714624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 715624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 716624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 717624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 718624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 719624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 720624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 721624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 722624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 723a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDQuad::debugSet(const SkDPoint* pts) { 724a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 725a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 726a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 727a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 728a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDCubic::debugSet(const SkDPoint* pts) { 729a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark memcpy(fPts, pts, sizeof(fPts)); 730a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark SkDEBUGCODE(fDebugGlobalState = nullptr); 731a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 732a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 733a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkvoid SkDConic::debugSet(const SkDPoint* pts, SkScalar weight) { 734a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fPts.debugSet(pts); 735a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark fWeight = weight; 736a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark} 737a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark 738ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 739ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 740ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 741ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 7424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 743570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 744570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 745ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 74655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT() 747ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* SkOpSegment::debugAddT(double t, SkPathOpsDebug::GlitchLog* log) const { 74855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 74955888e44171ffd48b591d19256884a969fe4da17caryclark SkPoint pt = this->ptAtT(t); 75055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* span = &fHead; 75126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 75255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* result = span->ptT(); 75329b2563afb1677515739f1d24fb27733626eca92caryclark if (t == result->fT || this->match(result, this, t, pt)) { 75455888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 755ef4f32ac858825dc443cfe4739ea878fb0bf550fcaryclark return result; 75655888e44171ffd48b591d19256884a969fe4da17caryclark } 75755888e44171ffd48b591d19256884a969fe4da17caryclark if (t < result->fT) { 75855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = result->span()->prev(); 75930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(!prev, span); 76029b2563afb1677515739f1d24fb27733626eca92caryclark // marks in global state that new op span has been allocated 76129b2563afb1677515739f1d24fb27733626eca92caryclark this->globalState()->setAllocatedOpSpan(); 76255888e44171ffd48b591d19256884a969fe4da17caryclark// span->init(this, prev, t, pt); 76355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 76455888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 76555888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 76655888e44171ffd48b591d19256884a969fe4da17caryclark// span->segment()->debugID(), span->debugID()); 76755888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 76855888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 76955888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 77055888e44171ffd48b591d19256884a969fe4da17caryclark } 77130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(span != &fTail, span); 77255888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->upCast()->next())); 77355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 77429b2563afb1677515739f1d24fb27733626eca92caryclark return nullptr; // we never get here, but need this to satisfy compiler 77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 78455888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 79255888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 79626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 79726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 79826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 799ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 801ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugCheckHealth(SkPathOpsDebug::GlitchLog* glitches) const { 802ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveMultiples(glitches); 803ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMoveNearby(glitches); 804ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark debugMissingCoincidence(glitches); 80555888e44171ffd48b591d19256884a969fe4da17caryclark} 80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 80755888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll() 808ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const { 80955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span = &fHead; 81055888e44171ffd48b591d19256884a969fe4da17caryclark do { 811ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugClearOne(span, glitches); 81255888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->next()->upCastable())); 813ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->globalState()->coincidence()->debugRelease(glitches, this); 81426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 81526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 81655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne() 817ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const { 818ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->windValue()) glitches->record(SkPathOpsDebug::kCollapsedWindValue_Glitch, span); 819ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->oppValue()) glitches->record(SkPathOpsDebug::kCollapsedOppValue_Glitch, span); 820ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span->done()) glitches->record(SkPathOpsDebug::kCollapsedDone_Glitch, span); 82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 82226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 82326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 82454359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 82596fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 82654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 82754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 82854359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 829dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 83054359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 831dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 83254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 833dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 834dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 835dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 836dac1d17027dcaa5596885a9f333979418b35001ccaryclark 837ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 83855888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited 83955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 84055888e44171ffd48b591d19256884a969fe4da17caryclark // reset visited flag back to false 84155888e44171ffd48b591d19256884a969fe4da17caryclark do { 84255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 84355888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != stopPtT) { 84455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->segment(); 84555888e44171ffd48b591d19256884a969fe4da17caryclark opp->resetDebugVisited(); 84655888e44171ffd48b591d19256884a969fe4da17caryclark } 84755888e44171ffd48b591d19256884a969fe4da17caryclark } while (!span->final() && (span = span->upCast()->next())); 84855888e44171ffd48b591d19256884a969fe4da17caryclark} 84955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 85055888e44171ffd48b591d19256884a969fe4da17caryclark 851ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 85255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence() 85355888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves 85455888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear 85555888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed 85655888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given 85755888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C: 85855888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 85955888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C. 86055888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2, 86155888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B. 862ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 86855888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 87326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 87426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->span()->segment(); 87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 88155888e44171ffd48b591d19256884a969fe4da17caryclark if (!opp->debugVisited()) { 88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88755888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this) { 88855888e44171ffd48b591d19256884a969fe4da17caryclark continue; 88955888e44171ffd48b591d19256884a969fe4da17caryclark } 89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 89355888e44171ffd48b591d19256884a969fe4da17caryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 89655888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89855888e44171ffd48b591d19256884a969fe4da17caryclark } 89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 90726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 90826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 909ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = priorPtT->span()->segment(); 91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 91726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 91926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 92026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 92155888e44171ffd48b591d19256884a969fe4da17caryclark if (priorPtT == ptT) { 92255888e44171ffd48b591d19256884a969fe4da17caryclark continue; 92355888e44171ffd48b591d19256884a969fe4da17caryclark } 92426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 92526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 92626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 92726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 92826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 92926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 93026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 93155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 93255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 93355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPtT = ptT->span()->ptT(); 93455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 93555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 93655888e44171ffd48b591d19256884a969fe4da17caryclark if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 93726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 93826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 93955888e44171ffd48b591d19256884a969fe4da17caryclark if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 94055888e44171ffd48b591d19256884a969fe4da17caryclark // mark coincidence 94130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE 94255888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 94355888e44171ffd48b591d19256884a969fe4da17caryclark// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 94455888e44171ffd48b591d19256884a969fe4da17caryclark// rootOppEnd->debugID()); 94555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 946ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMissingCoin_Glitch, priorPtT, ptT, oppStart, oppEnd); 94755888e44171ffd48b591d19256884a969fe4da17caryclark // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 94855888e44171ffd48b591d19256884a969fe4da17caryclark // } 94955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 950d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 95155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 95255888e44171ffd48b591d19256884a969fe4da17caryclark // result = true; 95326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 95426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 95526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 95626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 95726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 96055888e44171ffd48b591d19256884a969fe4da17caryclark DebugClearVisited(&fHead); 96155888e44171ffd48b591d19256884a969fe4da17caryclark return; 96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 96455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples() 96555888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed 966ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const { 96755888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 971ff11428526843d3e03feb6843bd21f2d80536415Cary Clark// SkASSERT(addCount >= 1); 972ff11428526843d3e03feb6843bd21f2d80536415Cary Clark if (addCount <= 1) { 97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 100326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 100426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 100526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 100626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 100726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 100826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 100926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 101126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 101226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 101426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 101526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 101726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 101826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 101926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 102026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 102226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 102326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 102426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 102526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 102626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 102726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 102826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 102926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 103026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 103126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 103226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 103326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 103426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 103526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 103626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 103726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 103826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 103926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 104026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 104126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 104226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 104355888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 1044ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugMergeMatches(glitches, oppSpan); 1045ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTest->debugAddOpp(glitches, oppSpan); 104655888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 104726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 104826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 104955888e44171ffd48b591d19256884a969fe4da17caryclark tryNextSpan: 105026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 105126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 105226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 105355888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan: 105426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 105526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 105655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 105755888e44171ffd48b591d19256884a969fe4da17caryclark return; 105826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 105926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 106055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby() 106155888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1062ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSegment::debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const { 106355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 106455888e44171ffd48b591d19256884a969fe4da17caryclark // release undeleted spans pointing to this seg that are linked to the primary span 106555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* spanBase = &fHead; 106626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 106755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = spanBase->ptT(); 106855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* headPtT = ptT; 106955888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != headPtT) { 107055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = ptT->span(); 107155888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this && !ptT->deleted() && test != spanBase 107255888e44171ffd48b591d19256884a969fe4da17caryclark && test->ptT() == ptT) { 107355888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 107455888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase == &fHead) { 1075ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll_Glitch, this); 107655888e44171ffd48b591d19256884a969fe4da17caryclark// return; 107755888e44171ffd48b591d19256884a969fe4da17caryclark } 1078ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyReleaseFinal_Glitch, spanBase, ptT); 107955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (test->prev()) { 1080ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyRelease_Glitch, test, headPtT); 108155888e44171ffd48b591d19256884a969fe4da17caryclark } 108255888e44171ffd48b591d19256884a969fe4da17caryclark// break; 108326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 108426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 108555888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = spanBase->upCast()->next(); 108655888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 108755888e44171ffd48b591d19256884a969fe4da17caryclark 108855888e44171ffd48b591d19256884a969fe4da17caryclark // This loop looks for adjacent spans which are near by 108955888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = &fHead; 109055888e44171ffd48b591d19256884a969fe4da17caryclark do { // iterate through all spans associated with start 109155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = spanBase->upCast()->next(); 1092c7c76d81fd09332a9a1d4b9f19b2a2dab3c723c3Cary Clark bool found; 1093c7c76d81fd09332a9a1d4b9f19b2a2dab3c723c3Cary Clark if (!this->spansNearby(spanBase, test, &found)) { 1094c7c76d81fd09332a9a1d4b9f19b2a2dab3c723c3Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 1095c7c76d81fd09332a9a1d4b9f19b2a2dab3c723c3Cary Clark } 1096c7c76d81fd09332a9a1d4b9f19b2a2dab3c723c3Cary Clark if (found) { 109755888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 109855888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->prev()) { 1099ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 110055888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1101ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyClearAll2_Glitch, this); 110255888e44171ffd48b591d19256884a969fe4da17caryclark // return 110355888e44171ffd48b591d19256884a969fe4da17caryclark } 110455888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1105ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark glitches->record(SkPathOpsDebug::kMoveNearbyMerge_Glitch, spanBase); 110655888e44171ffd48b591d19256884a969fe4da17caryclark } 110755888e44171ffd48b591d19256884a969fe4da17caryclark } 110855888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = test; 110955888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 111055888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 11144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 11151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 11164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1118025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 1119025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const { 1120025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { 1121025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = index; 1122025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = SkTMin(t, fDebugBaseMin); 1123025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = SkTMax(t, fDebugBaseMax); 1124025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1125025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1126025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); 1127025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugLastMax < 0 || fDebugLastIndex == index) { 1128025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = index; 1129025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = SkTMin(t, fDebugLastMin); 1130025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = SkTMax(t, fDebugLastMax); 1131025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 1132025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 1133025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); 1134025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); 1135025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 1136025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 1137025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 113854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 1139ff11428526843d3e03feb6843bd21f2d80536415Cary Clarkvoid SkOpSegment::debugShowActiveSpans(SkString* str) const { 11404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 11414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 11424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 11434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 11454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 114654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 114754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 114854359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 11494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 11524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 11534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 115554359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 1156ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf("%s id=%d", __FUNCTION__, this->debugID()); 115755888e44171ffd48b591d19256884a969fe4da17caryclark // since endpoints may have be adjusted, show actual computed curves 115855888e44171ffd48b591d19256884a969fe4da17caryclark SkDCurve curvePart; 115955888e44171ffd48b591d19256884a969fe4da17caryclark this->subDivide(span, span->next(), &curvePart); 116055888e44171ffd48b591d19256884a969fe4da17caryclark const SkDPoint* pts = curvePart.fCubic.fPts; 1161ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 11624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 1163ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 11644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 11651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 1166ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" %1.9gf", curvePart.fConic.fWeight); 11671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 1168ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 116954359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 1170ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" windSum=?"); 11714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1172ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" windSum=%d", span->windSum()); 1173624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1174624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 1175ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" oppSum=?"); 1176624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1177ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" oppSum=%d", span->oppSum()); 1178624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1179ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" windValue=%d", span->windValue()); 1180624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 1181ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf(" oppValue=%d", span->oppValue()); 11824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1183ff11428526843d3e03feb6843bd21f2d80536415Cary Clark str->appendf("\n"); 118454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 11854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 11864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 11874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 118854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 118954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 119054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 11911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 11924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 11934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 11944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 11954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 119654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 119754359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 119854359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 11994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 120154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 12024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 120354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 120454359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 120554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 120654359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 120754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 120854359294a7c9dc54802d512a5d891a35c1663392caryclark } 120954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 12104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 12114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 121254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 12134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 121454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 12151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 12164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 12174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 12184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 12194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 122054359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 122154359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 122254359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 122354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 122454359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 122554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 122654359294a7c9dc54802d512a5d891a35c1663392caryclark } 122754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 122854359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 122954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 123054359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 123154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 123254359294a7c9dc54802d512a5d891a35c1663392caryclark } 123354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 123454359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 12354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 123754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 12384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 12394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 124054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 12414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 12424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 124354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 12444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 124554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 12464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 124754359294a7c9dc54802d512a5d891a35c1663392caryclark 12484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 12494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 125355888e44171ffd48b591d19256884a969fe4da17caryclark This checks the distance between start points; the distance between 125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 128026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 128126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 128226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 128326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 128426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 128526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 128626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 128726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 128826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 128926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 129026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 129155888e44171ffd48b591d19256884a969fe4da17caryclark } while (test->fNext != this); 129226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 129326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 129426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 129554359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 129654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 129754359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 129854359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 129954359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 1300eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fPart.fCurve), 130154359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 130254359294a7c9dc54802d512a5d891a35c1663392caryclark break; 130354359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 1304eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fPart.fCurve), 130554359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 130654359294a7c9dc54802d512a5d891a35c1663392caryclark break; 13071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 13081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 1309eed356d281adbf93ecbd89cb23913a7861cd8578caryclark CONIC_DEBUG_DATA(fPart.fCurve, fPart.fCurve.fConic.fWeight), 13101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 13111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 131254359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 1313eed356d281adbf93ecbd89cb23913a7861cd8578caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fPart.fCurve), 131454359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 131554359294a7c9dc54802d512a5d891a35c1663392caryclark break; 131654359294a7c9dc54802d512a5d891a35c1663392caryclark default: 131754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 13181b24933e52f50773de29332387a12721811f3012mtklein } 131954359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 132054359294a7c9dc54802d512a5d891a35c1663392caryclark} 132154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 132254359294a7c9dc54802d512a5d891a35c1663392caryclark 1323624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 132454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 132554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 132654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 132754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 132854359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 132954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 133054359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 133154359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 133254359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 133354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 133454359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 133554359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 133654359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1337ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1338ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1339ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 134054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 134155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 134255888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 134355888e44171ffd48b591d19256884a969fe4da17caryclark return; 134455888e44171ffd48b591d19256884a969fe4da17caryclark } 134555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 134654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 134754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 134854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 134954359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 135054359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 135154359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 135254359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 135354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 135454359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 135554359294a7c9dc54802d512a5d891a35c1663392caryclark return; 135654359294a7c9dc54802d512a5d891a35c1663392caryclark } 135754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 135854359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 135954359294a7c9dc54802d512a5d891a35c1663392caryclark return; 136054359294a7c9dc54802d512a5d891a35c1663392caryclark } 136154359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 136254359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 136354359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 136454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 136554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 136654359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 136754359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 136854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 136954359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1370624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 137154359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 137254359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 137354359294a7c9dc54802d512a5d891a35c1663392caryclark } 137454359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 137554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 137654359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1377624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 137854359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 137954359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 138054359294a7c9dc54802d512a5d891a35c1663392caryclark } 138154359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 138254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 138359d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail); 138459d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail); 138554359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 138654359294a7c9dc54802d512a5d891a35c1663392caryclark} 138754359294a7c9dc54802d512a5d891a35c1663392caryclark 138854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 138954359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 139054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 139154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 139254359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 139354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1394f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 139554359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 139654359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 139754359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 139854359294a7c9dc54802d512a5d891a35c1663392caryclark break; 139954359294a7c9dc54802d512a5d891a35c1663392caryclark } 1400f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 140154359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 140254359294a7c9dc54802d512a5d891a35c1663392caryclark return; 140354359294a7c9dc54802d512a5d891a35c1663392caryclark } 140454359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 140554359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 140654359294a7c9dc54802d512a5d891a35c1663392caryclark} 140754359294a7c9dc54802d512a5d891a35c1663392caryclark 140855888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG 140955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 141055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpGlobalState* debugState) const { 141159d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail()); 141259d5a0e3f560da40e0ae7036a01d7d58ce3718d8Cary Clark SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail()); 141355888e44171ffd48b591d19256884a969fe4da17caryclark} 141455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 141526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 1417ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// sets the span's end to the ptT referenced by the previous-next 1418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log, 1419ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, 1420ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) const ) const { 1421ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* origPtT = (this->*getEnd)(); 1422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* origSpan = origPtT->span(); 1423ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = origSpan->prev(); 1424ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = prev ? prev->next()->ptT() 1425ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : origSpan->upCast()->next()->prev()->ptT(); 1426ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (origPtT != testPtT) { 1427ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCorrectEnd_Glitch, this, origPtT, testPtT); 1428ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1429ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1430ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1431ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1432ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* Commented-out lines keep this in sync with correctEnds */ 1433ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// FIXME: member pointers have fallen out of favor and can be replaced with 1434ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// an alternative approach. 1435ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// makes all span ends agree with the segment's spans that define them 1436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkCoincidentSpans::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 1437ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTStart, nullptr); 1438ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTEnd, nullptr); 1439ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTStart, nullptr); 1440ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTEnd, nullptr); 1441ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1442ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 144355888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */ 144430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// expand the range by checking adjacent spans for coincidence 1445ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkCoincidentSpans::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 144655888e44171ffd48b591d19256884a969fe4da17caryclark bool expanded = false; 144755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = coinPtTStart()->segment(); 144855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSegment = oppPtTStart()->segment(); 144955888e44171ffd48b591d19256884a969fe4da17caryclark do { 145055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coinPtTStart()->span()->upCast(); 145155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = start->prev(); 145255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 145355888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev || !(oppPtT = prev->contains(oppSegment))) { 145455888e44171ffd48b591d19256884a969fe4da17caryclark break; 145555888e44171ffd48b591d19256884a969fe4da17caryclark } 145655888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (prev->t() + start->t()) / 2; 145755888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 145855888e44171ffd48b591d19256884a969fe4da17caryclark break; 145955888e44171ffd48b591d19256884a969fe4da17caryclark } 1460ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, prev->ptT(), oppPtT); 146155888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 146255888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 146355888e44171ffd48b591d19256884a969fe4da17caryclark do { 146455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coinPtTEnd()->span(); 146555888e44171ffd48b591d19256884a969fe4da17caryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 146630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (next && next->deleted()) { 146730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 146830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 146955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 147055888e44171ffd48b591d19256884a969fe4da17caryclark if (!next || !(oppPtT = next->contains(oppSegment))) { 147155888e44171ffd48b591d19256884a969fe4da17caryclark break; 147255888e44171ffd48b591d19256884a969fe4da17caryclark } 147355888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (end->t() + next->t()) / 2; 147455888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 147555888e44171ffd48b591d19256884a969fe4da17caryclark break; 147655888e44171ffd48b591d19256884a969fe4da17caryclark } 1477ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, next->ptT(), oppPtT); 147855888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 147955888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 148055888e44171ffd48b591d19256884a969fe4da17caryclark return expanded; 148155888e44171ffd48b591d19256884a969fe4da17caryclark} 148255888e44171ffd48b591d19256884a969fe4da17caryclark 1483ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1484ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* base, const SkOpSpanBase* testSpan) const { 1485ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* testPtT = testSpan->ptT(); 1486ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* stopPtT = testPtT; 1487ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* baseSeg = base->segment(); 1488ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark while ((testPtT = testPtT->next()) != stopPtT) { 1489ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* testSeg = testPtT->segment(); 1490ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->deleted()) { 1491ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1492ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1493ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testSeg == baseSeg) { 1494ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1495ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1496ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (testPtT->span()->ptT() != testPtT) { 1497ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1498ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1499ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->contains(baseSeg, testSeg, testPtT->fT)) { 1500ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1501ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1502ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // intersect perp with base->ptT() with testPtT->segment() 1503ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDVector dxdy = baseSeg->dSlopeAtT(base->t()); 1504ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkPoint& pt = base->pt(); 1505ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}}; 1506ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkIntersections i; 1507ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i); 1508ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark for (int index = 0; index < i.used(); ++index) { 1509ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double t = i[0][index]; 1510ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!between(0, t, 1)) { 1511ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1512ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1513ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkDPoint oppPt = i.pt(index); 1514ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oppPt.approximatelyEqual(pt)) { 1515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1516ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1517ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg); 1518ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPtT* oppStart = writableSeg->addT(t); 1519ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart == testPtT) { 1520ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1521ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1522ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSpan* writableBase = const_cast<SkOpSpan*>(base); 1523ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppStart->span()->addOpp(writableBase); 1524ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oppStart->deleted()) { 1525ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark continue; 1526ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1527ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* coinSeg = base->segment(); 1528ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpSegment* oppSeg = oppStart->segment(); 1529ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double coinTs, coinTe, oppTs, oppTe; 1530ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (Ordered(coinSeg, oppSeg)) { 1531ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = base->t(); 1532ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testSpan->t(); 1533ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = oppStart->fT; 1534ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testPtT->fT; 1535ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1536ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinSeg, oppSeg); 1537ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTs = oppStart->fT; 1538ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coinTe = testPtT->fT; 1539ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTs = base->t(); 1540ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oppTe = testSpan->t(); 1541ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1542ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coinTs > coinTe) { 1543ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(coinTs, coinTe); 1544ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkTSwap(oppTs, oppTe); 1545ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1546ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool added; 1547ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added), false) { 1548ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1549ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1550ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1551ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1552ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1553ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1554ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1555ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// description below 1556ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* ptT) const { 1557ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!ptT->span()->upCastable(), ptT->span()); 1558ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* base = ptT->span()->upCast(); 1559ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* prev = base->prev(); 1560ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!prev, ptT->span()); 1561ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!prev->isCanceled()) { 1562ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->prev()), false) { 1563ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1564ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1565ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1566ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!base->isCanceled()) { 1567ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, base, base->next()), false) { 1568ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1569ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1570ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1571ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1572ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1573ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 1574ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark/* If A is coincident with B and B includes an endpoint, and A's matching point 1575ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark is not the endpoint (i.e., there's an implied line connecting B-end and A) 1576ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark then assume that the same implied line may intersect another curve close to B. 1577ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark Since we only care about coincidence that was undetected, look at the 1578ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but 1579ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark next door) and see if the A matching point is close enough to form another 1580ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coincident pair. If so, check for a new coincident span between B-end/A ptT loop 1581ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark and the adjacent ptT loop. 1582ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark*/ 1583ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const { 1584ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* span = fHead; 1585ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!span) { 1586ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1587ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1588ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fTop = span; 1589ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// fHead = nullptr; 1590ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1591ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) { 1592ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(1 == span->coinPtTStart()->fT, span); 1593ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTStart()->fT == 0; 1594ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTStart()->fT); 1595ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1596ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { // if both are on end, any nearby intersect was already found 1597ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTStart()), false) { 1598ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1599ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1600ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1601ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1602ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTStart()), false) { 1603ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1604ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1605ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1606ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1607ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) { 1608ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool onEnd = span->coinPtTEnd()->fT == 1; 1609ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT); 1610ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (onEnd) { 1611ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!oOnEnd) { 1612ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->oppPtTEnd()), false) { 1613ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1614ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1615ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1616ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (oOnEnd) { 1617ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (this->debugAddEndMovedSpans(log, span->coinPtTEnd()), false) { 1618ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1619ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1620ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1621ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 1622ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((span = span->next())); 1623ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark// this->restoreHead(); 1624ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1625ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 1626ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 162755888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */ 162855888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans 162955888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 1630ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddExpanded(SkPathOpsDebug::GlitchLog* log) const { 1631a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark// DEBUG_SET_PHASE(); 163226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 163326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 1634ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1635ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 163626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 163755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* startPtT = coin->coinPtTStart(); 163855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oStartPtT = coin->oppPtTStart(); 1639ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double priorT = startPtT->fT; 1640ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double oPriorT = oStartPtT->fT; 1641ff11428526843d3e03feb6843bd21f2d80536415Cary Clark FAIL_IF(!startPtT->contains(oStartPtT), coin); 1642ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 164326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 164426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 164555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 164655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 164730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(oEnd->deleted(), coin); 164830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!start->upCastable(), coin); 164926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 1650ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->flipped() && !oStart->upCastable(), coin); 165155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 1652ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 1653ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* seg = start->segment(); 1654ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* oSeg = oStart->segment(); 165526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 1656ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedOpp = test->ptT()->contains(oSeg); 1657ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* containedThis = oTest->ptT()->contains(seg); 1658ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!containedOpp || !containedThis) { 1659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // choose the ends, or the first common pt-t list shared by both 1660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark double nextT, oNextT; 1661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (containedOpp) { 1662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = test->t(); 1663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = containedOpp->fT; 1664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else if (containedThis) { 1665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = containedThis->fT; 1666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = oTest->t(); 1667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } else { 1668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // iterate through until a pt-t list found that contains the other 1669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* walk = test; 1670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* walkOpp; 1671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 1672ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!walk->upCastable(), coin); 1673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark walk = walk->upCast()->next(); 1674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while (!(walkOpp = walk->ptT()->contains(oSeg)) 1675ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark && walk != coin->coinPtTEnd()->span()); 1676a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!walkOpp, coin); 1677ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark nextT = walk->t(); 1678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oNextT = walkOpp->fT; 1679ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 168026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 1681a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startRange = nextT - priorT; 168230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!startRange, coin); 1683a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double startPart = (test->t() - priorT) / startRange; 1684a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark double oStartRange = oNextT - oPriorT; 168530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!oStartRange, coin); 168626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 168730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(startPart == oStartPart, coin); 1688ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart 1689ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : !!containedThis; 169055888e44171ffd48b591d19256884a969fe4da17caryclark bool startOver = false; 1691ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark addToOpp ? log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1692ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT + oStartRange * startPart, test) 1693ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark : log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1694ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT + startRange * oStartPart, oTest); 1695ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark // FAIL_IF(!success, coin); 169655888e44171ffd48b591d19256884a969fe4da17caryclark if (startOver) { 169755888e44171ffd48b591d19256884a969fe4da17caryclark test = start; 169855888e44171ffd48b591d19256884a969fe4da17caryclark oTest = oStart; 169926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1700ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end = coin->coinPtTEnd()->span(); 1701ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oEnd = coin->oppPtTEnd()->span(); 170226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170355888e44171ffd48b591d19256884a969fe4da17caryclark if (test != end) { 1704ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!test->upCastable(), coin); 1705ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark priorT = test->t(); 170626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 170726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170855888e44171ffd48b591d19256884a969fe4da17caryclark if (oTest != oEnd) { 1709ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oPriorT = oTest->t(); 171055888e44171ffd48b591d19256884a969fe4da17caryclark oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 1711ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oTest, coin); 171226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 171555888e44171ffd48b591d19256884a969fe4da17caryclark return; 171655888e44171ffd48b591d19256884a969fe4da17caryclark} 171755888e44171ffd48b591d19256884a969fe4da17caryclark 171855888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */ 17198016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// note that over1s, over1e, over2s, over2e are ordered 1720ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddIfMissing(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s, 172181a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added, 17228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* over1e, const SkOpPtT* over2e) const { 17238016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(tStart < tEnd); 17248016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->fT < over1e->fT); 17258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tStart, over1e->fT)); 17268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 17278016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->fT < over2e->fT); 17288016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tStart, over2e->fT)); 17298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 17308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over1e->segment()); 17318016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over2s->segment() == over2e->segment()); 17328016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() == over2s->segment()); 17338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != coinSeg); 17348016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(over1s->segment() != oppSeg); 17358016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(coinSeg != oppSeg); 173626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 17378016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 17388016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 17398016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinSeg->collapsed(coinTs, coinTe)) { 1740ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, coinSeg); 174126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 17438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 17448016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (oppSeg->collapsed(oppTs, oppTe)) { 1745ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, oppSeg); 174626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17478016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (coinTs > coinTe) { 17488016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkTSwap(coinTs, coinTe); 174926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 175026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1751ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added 17528016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ); 175355888e44171ffd48b591d19256884a969fe4da17caryclark} 175455888e44171ffd48b591d19256884a969fe4da17caryclark 175555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */ 175630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 175730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 1758ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log, 175930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 176081a478ca6c36aac3e53ce0373a281ac8940f4780caryclark double coinTs, double coinTe, double oppTs, double oppTe, bool* added) const { 176155888e44171ffd48b591d19256884a969fe4da17caryclark SkTDArray<SkCoincidentSpans*> overlaps; 1762ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOPASSERT(!fTop); // this is (correctly) reversed in addifMissing() 176381a478ca6c36aac3e53ce0373a281ac8940f4780caryclark if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, 176481a478ca6c36aac3e53ce0373a281ac8940f4780caryclark &overlaps)) { 176555888e44171ffd48b591d19256884a969fe4da17caryclark return; 176655888e44171ffd48b591d19256884a969fe4da17caryclark } 176755888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 176855888e44171ffd48b591d19256884a969fe4da17caryclark coinTe, oppTs, oppTe, &overlaps)) { 176955888e44171ffd48b591d19256884a969fe4da17caryclark return; 177055888e44171ffd48b591d19256884a969fe4da17caryclark } 177155888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 177255888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 177355888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = overlaps[index]; 177455888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 1775ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTStart()); 177655888e44171ffd48b591d19256884a969fe4da17caryclark } 177755888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 1778ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTEnd()); 177955888e44171ffd48b591d19256884a969fe4da17caryclark } 178055888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 178155888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 178255888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 1783ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTStart()); 178455888e44171ffd48b591d19256884a969fe4da17caryclark } 178555888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 178655888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 178755888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 1788ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTEnd()); 178955888e44171ffd48b591d19256884a969fe4da17caryclark } 1790ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!fHead) { this->debugRelease(log, fHead, test); 1791ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, fTop, test); 179255888e44171ffd48b591d19256884a969fe4da17caryclark } 179355888e44171ffd48b591d19256884a969fe4da17caryclark } 179455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 179555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 179630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); 179730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(cs != ce || !cs, coinSeg); 179855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 179955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 180030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); 180155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !cs || !cs->deleted()); 180255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !os || !os->deleted()); 180355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !ce || !ce->deleted()); 180455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !oe || !oe->deleted()); 180555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 180655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 180730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); 180830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && (csExisting == ce || 180930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); 181030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceExisting && (ceExisting == cs || 181130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); 181255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 181355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 181430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); 181530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && (osExisting == oe || 181630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); 181730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeExisting && (oeExisting == os || 181830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oeExisting->contains(osExisting ? osExisting : os)), oppSeg); 181955888e44171ffd48b591d19256884a969fe4da17caryclark bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 182055888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 182155888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !os) { 182255888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs) 1823ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark cs = coinSeg->debugAddT(coinTs, log); 182455888e44171ffd48b591d19256884a969fe4da17caryclark if (!os) 1825ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark os = oppSeg->debugAddT(oppTs, log); 182630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 1827ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (cs && os) cs->span()->debugAddOpp(log, os->span()); 182855888e44171ffd48b591d19256884a969fe4da17caryclark// cs = csWritable; 182930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// os = osWritable->active(); 183030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg); 183155888e44171ffd48b591d19256884a969fe4da17caryclark } 183255888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce || !oe) { 183355888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce) 1834ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark ce = coinSeg->debugAddT(coinTe, log); 183555888e44171ffd48b591d19256884a969fe4da17caryclark if (!oe) 1836ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark oe = oppSeg->debugAddT(oppTe, log); 1837ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ce && oe) ce->span()->debugAddOpp(log, oe->span()); 183855888e44171ffd48b591d19256884a969fe4da17caryclark// ce = ceWritable; 183955888e44171ffd48b591d19256884a969fe4da17caryclark// oe = oeWritable; 184055888e44171ffd48b591d19256884a969fe4da17caryclark } 184155888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 184230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csDeleted, coinSeg); 184330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osDeleted, oppSeg); 184430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceDeleted, coinSeg); 184530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeDeleted, oppSeg); 18468016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg); 18478016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark bool result = true; 184855888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap) { 184955888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->segment() == coinSeg) { 1850ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 185155888e44171ffd48b591d19256884a969fe4da17caryclark } else { 185255888e44171ffd48b591d19256884a969fe4da17caryclark if (oppTs > oppTe) { 185355888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 185455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(oppTs, oppTe); 185555888e44171ffd48b591d19256884a969fe4da17caryclark } 1856ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 185755888e44171ffd48b591d19256884a969fe4da17caryclark } 18588016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18598016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (result) { 18608016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark overlap->debugShow(); 18618016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark } 186255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 186355888e44171ffd48b591d19256884a969fe4da17caryclark } else { 1864ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kAddMissingCoin_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 18658016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark#if 0 && DEBUG_COINCIDENCE_VERBOSE 18668016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark fHead->debugShow(); 186755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 186855888e44171ffd48b591d19256884a969fe4da17caryclark } 186955888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 18708016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return (void) result; 187126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 187226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 187355888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing() 187455888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */ 187555888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */ 187655888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again 1877ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugAddMissing(SkPathOpsDebug::GlitchLog* log, bool* added) const { 187826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 1879ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark *added = false; 188026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 188126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 188226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 188355888e44171ffd48b591d19256884a969fe4da17caryclark // fTop = outer; 188455888e44171ffd48b591d19256884a969fe4da17caryclark // fHead = nullptr; 188526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 188626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 188726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 188826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 18898016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ocs = outer->coinPtTStart(); 18908016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ocs->deleted()); 18918016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerCoin = ocs->segment(); 18928016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 18938016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oos = outer->oppPtTStart(); 1894ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oos->deleted()) { 1895ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1896ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 18978016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* outerOpp = oos->segment(); 18988016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!outerOpp->done()); 18998016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 19008016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 190126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 190255888e44171ffd48b591d19256884a969fe4da17caryclark while ((inner = inner->next())) { 190355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 190426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 19058016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ics = inner->coinPtTStart(); 19068016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ics->deleted()); 19078016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerCoin = ics->segment(); 19088016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerCoin->done()); 19098016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ios = inner->oppPtTStart(); 19108016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ios->deleted()); 19118016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpSegment* innerOpp = ios->segment(); 19128016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!innerOpp->done()); 19138016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin); 19148016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark// SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 191555888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin == innerCoin) { 19168016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 1917ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oce->deleted()) { 1918ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1919ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 19208016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19218016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 19228016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) { 1923ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ics->starter(ice), 192481a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerOpp, added, 19258016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19268016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 192726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 192855888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerCoin == innerOpp) { 19298016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* oce = outer->coinPtTEnd(); 19308016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!oce->deleted()); 19318016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 19328016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ioe->deleted()); 19338016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) { 1934ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, ocs->starter(oce), ios->starter(ioe), 193581a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerOpp, innerCoin, added, 19368016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ocs->debugEnder(oce), 19378016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 193826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 193955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerCoin) { 19408016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19418016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19428016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ice = inner->coinPtTEnd(); 19438016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ice->deleted()); 194455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerOpp); 19458016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 1946ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ics->starter(ice), 194781a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerOpp, added, 19488016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19498016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ics->debugEnder(ice)); 195026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 195155888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerOpp) { 19528016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ooe = outer->oppPtTEnd(); 19538016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark SkASSERT(!ooe->deleted()); 19548016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark const SkOpPtT* ioe = inner->oppPtTEnd(); 1955ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (ioe->deleted()) { 1956ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 1957ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 195855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerCoin); 19598016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 1960ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugAddIfMissing(log, oos->starter(ooe), ios->starter(ioe), 196181a478ca6c36aac3e53ce0373a281ac8940f4780caryclark overS, overE, outerCoin, innerCoin, added, 19628016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark oos->debugEnder(ooe), 19638016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark ios->debugEnder(ioe)); 196426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 196526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 196655888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 196755888e44171ffd48b591d19256884a969fe4da17caryclark } 196855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((outer = outer->next())); 196955888e44171ffd48b591d19256884a969fe4da17caryclark // this->restoreHead(); 197055888e44171ffd48b591d19256884a969fe4da17caryclark return; 197155888e44171ffd48b591d19256884a969fe4da17caryclark} 197255888e44171ffd48b591d19256884a969fe4da17caryclark 197355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release() 1974ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { 197530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 197630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* prev = nullptr; 197730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* next; 197830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 197930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark next = coin->next(); 198030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (coin == remove) { 198130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (prev) { 198230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// prev->setNext(next); 198330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else if (head == fHead) { 198430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fHead = next; 198530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 198630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fTop = next; 198730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 1988ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 198930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 199030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark prev = coin; 199130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((coin = next)); 199230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 199330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 199430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 1995ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 199655888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 199755888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 199855888e44171ffd48b591d19256884a969fe4da17caryclark return; 199955888e44171ffd48b591d19256884a969fe4da17caryclark } 200055888e44171ffd48b591d19256884a969fe4da17caryclark do { 200155888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->segment() == deleted 200255888e44171ffd48b591d19256884a969fe4da17caryclark || coin->coinPtTEnd()->segment() == deleted 200355888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTStart()->segment() == deleted 200455888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTEnd()->segment() == deleted) { 2005ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 200630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 200755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 200826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 200926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 201055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand() 201155888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence 2012ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkbool SkOpCoincidence::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 201326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 201426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 201526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 201626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 201726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 201826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2019ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (coin->debugExpand(log)) { 202055888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if multiple spans expanded so they are now identical 202155888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = fHead; 202255888e44171ffd48b591d19256884a969fe4da17caryclark do { 202355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin == test) { 202455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 202555888e44171ffd48b591d19256884a969fe4da17caryclark } 202655888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == test->coinPtTStart() 202755888e44171ffd48b591d19256884a969fe4da17caryclark && coin->oppPtTStart() == test->oppPtTStart()) { 2028ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, fHead, test->coinPtTStart()); 202955888e44171ffd48b591d19256884a969fe4da17caryclark break; 203055888e44171ffd48b591d19256884a969fe4da17caryclark } 203155888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next())); 203255888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 203326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 203455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 203526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 203626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 203726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 203855888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark() 203955888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 2040ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMark(SkPathOpsDebug::GlitchLog* log) const { 204126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 204226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 204326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 204426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 204526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2046ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable(), coin); 204755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 204855888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(start->deleted()); 204955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 205055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(end->deleted()); 205155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 205255888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oStart->deleted()); 205355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 205455888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oEnd->deleted()); 205555888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 205626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 205726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 205826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 205955888e44171ffd48b591d19256884a969fe4da17caryclark /* coin and opp spans may not match up. Mark the ends, and then let the interior 206055888e44171ffd48b591d19256884a969fe4da17caryclark get marked as many times as the spans allow */ 2061ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark start->debugInsertCoincidence(log, oStart->upCast()); 2062ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark end->debugInsertCoinEnd(log, oEnd); 206355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = start->segment(); 206455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oSegment = oStart->segment(); 206526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 206626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 2067a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark bool ordered; 2068a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark FAIL_IF(!coin->ordered(&ordered), coin); 206955888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->upCast()->next()) != end) { 2070ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!next->upCastable(), coin); 2071ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (next->upCast()->debugInsertCoincidence(log, oSegment, flipped, ordered), false) { 207255888e44171ffd48b591d19256884a969fe4da17caryclark return; 207326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 207455888e44171ffd48b591d19256884a969fe4da17caryclark } 207555888e44171ffd48b591d19256884a969fe4da17caryclark while ((oNext = oNext->upCast()->next()) != oEnd) { 2076ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!oNext->upCastable(), coin); 2077ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (oNext->upCast()->debugInsertCoincidence(log, segment, flipped, ordered), false) { 207855888e44171ffd48b591d19256884a969fe4da17caryclark return; 207926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 208055888e44171ffd48b591d19256884a969fe4da17caryclark } 208155888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 208255888e44171ffd48b591d19256884a969fe4da17caryclark return; 208355888e44171ffd48b591d19256884a969fe4da17caryclark} 208455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 208555888e44171ffd48b591d19256884a969fe4da17caryclark 2086ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 208755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2088ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 208930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 209055888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 209155888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->collapsed(test)) { 209255888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 2093ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 209426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 209555888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 2096ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 209755888e44171ffd48b591d19256884a969fe4da17caryclark } 2098ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugRelease(log, head, coin); 209955888e44171ffd48b591d19256884a969fe4da17caryclark } 210055888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 210155888e44171ffd48b591d19256884a969fe4da17caryclark } 210255888e44171ffd48b591d19256884a969fe4da17caryclark} 210355888e44171ffd48b591d19256884a969fe4da17caryclark 210455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 2105ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 2106ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fHead, test); 2107ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMarkCollapsed(log, fTop, test); 210826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 210926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 211026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 211155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const { 21126c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(), 211355888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->fT, coinPtTEnd()->fT); 21146c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(), 211555888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->fT, oppPtTEnd()->fT); 211655888e44171ffd48b591d19256884a969fe4da17caryclark} 211755888e44171ffd48b591d19256884a969fe4da17caryclark 2118624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 211955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 212055888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* span = fHead; 2121624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 212255888e44171ffd48b591d19256884a969fe4da17caryclark span->debugShow(); 212355888e44171ffd48b591d19256884a969fe4da17caryclark span = span->next(); 2124624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 212555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2126624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2127624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 2128ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 21296c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end, 213055888e44171ffd48b591d19256884a969fe4da17caryclark double oStart, double oEnd, const SkOpSegment* oSegment, 2131ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 213255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(next != end); 213355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!next->contains(end) || log); 213455888e44171ffd48b591d19256884a969fe4da17caryclark if (next->t() > end->t()) { 213555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(next, end); 213655888e44171ffd48b591d19256884a969fe4da17caryclark } 213755888e44171ffd48b591d19256884a969fe4da17caryclark do { 213855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = next->ptT(); 213955888e44171ffd48b591d19256884a969fe4da17caryclark int index = 0; 214027c015dfcf4e2b8fb1abe327cc40204e2a4f452acaryclark bool somethingBetween = false; 214155888e44171ffd48b591d19256884a969fe4da17caryclark do { 214255888e44171ffd48b591d19256884a969fe4da17caryclark ++index; 214355888e44171ffd48b591d19256884a969fe4da17caryclark ptT = ptT->next(); 214455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* checkPtT = next->ptT(); 214555888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT == checkPtT) { 214655888e44171ffd48b591d19256884a969fe4da17caryclark break; 214755888e44171ffd48b591d19256884a969fe4da17caryclark } 214855888e44171ffd48b591d19256884a969fe4da17caryclark bool looped = false; 214955888e44171ffd48b591d19256884a969fe4da17caryclark for (int check = 0; check < index; ++check) { 215055888e44171ffd48b591d19256884a969fe4da17caryclark if ((looped = checkPtT == ptT)) { 215155888e44171ffd48b591d19256884a969fe4da17caryclark break; 215255888e44171ffd48b591d19256884a969fe4da17caryclark } 215355888e44171ffd48b591d19256884a969fe4da17caryclark checkPtT = checkPtT->next(); 215455888e44171ffd48b591d19256884a969fe4da17caryclark } 215555888e44171ffd48b591d19256884a969fe4da17caryclark if (looped) { 215655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 215755888e44171ffd48b591d19256884a969fe4da17caryclark break; 215855888e44171ffd48b591d19256884a969fe4da17caryclark } 215955888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->deleted()) { 216055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 216155888e44171ffd48b591d19256884a969fe4da17caryclark } 216255888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() != oSegment) { 216355888e44171ffd48b591d19256884a969fe4da17caryclark continue; 216455888e44171ffd48b591d19256884a969fe4da17caryclark } 216555888e44171ffd48b591d19256884a969fe4da17caryclark somethingBetween |= between(oStart, ptT->fT, oEnd); 216655888e44171ffd48b591d19256884a969fe4da17caryclark } while (true); 216755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(somethingBetween); 216855888e44171ffd48b591d19256884a969fe4da17caryclark } while (next != end && (next = next->upCast()->next())); 216955888e44171ffd48b591d19256884a969fe4da17caryclark} 217055888e44171ffd48b591d19256884a969fe4da17caryclark 217155888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 2172ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 217355888e44171ffd48b591d19256884a969fe4da17caryclark if (!list) { 217455888e44171ffd48b591d19256884a969fe4da17caryclark return; 217555888e44171ffd48b591d19256884a969fe4da17caryclark } 217655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 217755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 217855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 217955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 218055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg != test->oppPtTStart()->segment()); 218155888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 218255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tcs, 1)); 218355888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 218455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tce, 1)); 218555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tcs < tce); 218655888e44171ffd48b591d19256884a969fe4da17caryclark double tos = test->oppPtTStart()->fT; 218755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tos, 1)); 218855888e44171ffd48b591d19256884a969fe4da17caryclark double toe = test->oppPtTEnd()->fT; 218955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, toe, 1)); 219055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tos != toe); 219155888e44171ffd48b591d19256884a969fe4da17caryclark if (tos > toe) { 219255888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(tos, toe); 219355888e44171ffd48b591d19256884a969fe4da17caryclark } 219455888e44171ffd48b591d19256884a969fe4da17caryclark do { 219555888e44171ffd48b591d19256884a969fe4da17caryclark double lcs, lce, los, loe; 219655888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == list->coinPtTStart()->segment()) { 219755888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->oppPtTStart()->segment()) { 219855888e44171ffd48b591d19256884a969fe4da17caryclark continue; 219955888e44171ffd48b591d19256884a969fe4da17caryclark } 220055888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->coinPtTStart()->fT; 220155888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->coinPtTEnd()->fT; 220255888e44171ffd48b591d19256884a969fe4da17caryclark los = list->oppPtTStart()->fT; 220355888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->oppPtTEnd()->fT; 220455888e44171ffd48b591d19256884a969fe4da17caryclark if (los > loe) { 220555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(los, loe); 220655888e44171ffd48b591d19256884a969fe4da17caryclark } 220755888e44171ffd48b591d19256884a969fe4da17caryclark } else if (coinSeg == list->oppPtTStart()->segment()) { 220855888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->coinPtTStart()->segment()) { 220955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 221055888e44171ffd48b591d19256884a969fe4da17caryclark } 221155888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->oppPtTStart()->fT; 221255888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->oppPtTEnd()->fT; 221355888e44171ffd48b591d19256884a969fe4da17caryclark if (lcs > lce) { 221455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(lcs, lce); 221555888e44171ffd48b591d19256884a969fe4da17caryclark } 221655888e44171ffd48b591d19256884a969fe4da17caryclark los = list->coinPtTStart()->fT; 221755888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->coinPtTEnd()->fT; 221855888e44171ffd48b591d19256884a969fe4da17caryclark } else { 221955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 222055888e44171ffd48b591d19256884a969fe4da17caryclark } 222155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tce < lcs || lce < tcs); 222255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(toe < los || loe < tos); 222355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((list = list->next())); 222455888e44171ffd48b591d19256884a969fe4da17caryclark} 222555888e44171ffd48b591d19256884a969fe4da17caryclark 222655888e44171ffd48b591d19256884a969fe4da17caryclark 222755888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2228ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 222955888e44171ffd48b591d19256884a969fe4da17caryclark // check for overlapping coincident spans 223055888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = head; 223155888e44171ffd48b591d19256884a969fe4da17caryclark while (test) { 223255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* next = test->next(); 2233ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, next, log); 2234ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlap(test, opt, log); 223555888e44171ffd48b591d19256884a969fe4da17caryclark test = next; 223655888e44171ffd48b591d19256884a969fe4da17caryclark } 223755888e44171ffd48b591d19256884a969fe4da17caryclark} 223855888e44171ffd48b591d19256884a969fe4da17caryclark 223955888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2240ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 224155888e44171ffd48b591d19256884a969fe4da17caryclark // look for pts inside coincident spans that are not inside the opposite spans 224255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = head; 224355888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 224455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 224555888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->segment())); 224655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 224755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 224855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 224955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 22506c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark coin = coin->next(); 22516c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2252ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 22536c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22546c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22556c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 22566c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugValidate() const { 22576c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#if DEBUG_COINCIDENCE 2258ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, nullptr); 2259ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, nullptr); 22606c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark#endif 22616c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark} 22626c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark 2263ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 22646c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkstatic void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2265ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkPathOpsDebug::GlitchLog* log) { 22666c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark // look for pts inside coincident spans that are not inside the opposite spans 22676c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark const SkCoincidentSpans* coin = head; 22686c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark while (coin) { 22696c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 227055888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 2271ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 22726c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 227355888e44171ffd48b591d19256884a969fe4da17caryclark coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 2274ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log); 227555888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 227655888e44171ffd48b591d19256884a969fe4da17caryclark } 2277ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckOverlapTop(head, opt, log); 227855888e44171ffd48b591d19256884a969fe4da17caryclark} 227955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 228055888e44171ffd48b591d19256884a969fe4da17caryclark 22816c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclarkvoid SkOpCoincidence::debugCheckBetween() const { 228255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 22836c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark if (fGlobalState->debugCheckHealth()) { 22846c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark return; 22856c3b9cdcb047afe963c7bcf34834ba2ecccacc33caryclark } 2286ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fHead, fTop, nullptr); 2287ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugCheckBetween(fTop, nullptr, nullptr); 228855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 228955888e44171ffd48b591d19256884a969fe4da17caryclark} 229055888e44171ffd48b591d19256884a969fe4da17caryclark 2291ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2292ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugCheckHealth(SkPathOpsDebug::GlitchLog* log) const { 2293ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2294ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2295ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugCheckHealth(log); 2296ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 229755888e44171ffd48b591d19256884a969fe4da17caryclark} 2298ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2299ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCheckValid(SkPathOpsDebug::GlitchLog* log) const { 2300ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_VALIDATE 2301ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fHead, fTop, log); 2302ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark DebugValidate(fTop, nullptr, log); 230355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2304ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 230555888e44171ffd48b591d19256884a969fe4da17caryclark 2306ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpCoincidence::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 2307ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkCoincidentSpans* coin = fHead; 2308ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!coin) { 2309ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2310ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 231126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2312ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coin->debugCorrectEnds(log); 2313ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((coin = coin->next())); 231426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 231526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 231655888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence() 2317ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 231855888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fCount > 0); 231926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 232055888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 232126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 2322e47ae2998c1cf944db5743a416583dd0f042b6d9Cary Clark if (segment->debugMissingCoincidence(log), false) { 232355888e44171ffd48b591d19256884a969fe4da17caryclark// result = true; 232455888e44171ffd48b591d19256884a969fe4da17caryclark } 232555888e44171ffd48b591d19256884a969fe4da17caryclark segment = segment->next(); 232655888e44171ffd48b591d19256884a969fe4da17caryclark } while (segment); 232755888e44171ffd48b591d19256884a969fe4da17caryclark return; 232826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 2329ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2330ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveMultiples(SkPathOpsDebug::GlitchLog* log) const { 2331ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2332ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2333ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2334ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (segment->debugMoveMultiples(log), false) { 2335ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2336ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2337ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2338ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 2339ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 2340ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark 2341ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpContour::debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const { 2342ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkASSERT(fCount > 0); 2343ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSegment* segment = &fHead; 2344ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark do { 2345ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark segment->debugMoveNearby(log); 2346ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } while ((segment = segment->next())); 2347ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark} 234826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 234926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2350025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2351025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugResetCoinT() const { 2352025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = -1; 2353025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = 1; 2354025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = -1; 2355025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = -1; 2356025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = 1; 2357025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = -1; 2358025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2359025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2360025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 23614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 2362025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2363025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark { 2364025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpSpanBase* span = &fHead; 2365025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2366025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugResetCoinT(); 2367025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2368025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span = &fHead; 2369025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark int index = 0; 2370025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2371025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugSetCoinT(index++); 2372025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2373025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2374025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 237555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 237655888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 237755888e44171ffd48b591d19256884a969fe4da17caryclark return; 237855888e44171ffd48b591d19256884a969fe4da17caryclark } 237955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 23804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 238154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 238254359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 238396fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 238454359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 23854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 238654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 238754359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 238854359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 238954359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 239054359294a7c9dc54802d512a5d891a35c1663392caryclark } 239154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 239254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 239354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 239454359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 239554359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 239654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 239754359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 239854359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 239954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 240054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 240154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 240208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 240354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 240454359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 240554359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 240654359294a7c9dc54802d512a5d891a35c1663392caryclark} 240754359294a7c9dc54802d512a5d891a35c1663392caryclark 2408ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 240930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 241030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with addOpp() 2411ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugAddOpp(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 241230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 241330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!oppPrev) { 241455888e44171ffd48b591d19256884a969fe4da17caryclark return; 241526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2416ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugMergeMatches(log, opp); 241730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->ptT()->debugAddOpp(opp->ptT(), oppPrev); 2418ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 241926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 242026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 242155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 2422ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* log) const { 242355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coins = this->globalState()->coincidence(); 242455888e44171ffd48b591d19256884a969fe4da17caryclark if (coins->isEmpty()) { 242555888e44171ffd48b591d19256884a969fe4da17caryclark return; 242655888e44171ffd48b591d19256884a969fe4da17caryclark } 242755888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span 242855888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop 242955888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span 243055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 243155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* test = head; 243226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 243355888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->coincident()) { 243455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 243526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 2436ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark coins->debugMarkCollapsed(log, test); 243755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next()) != head); 243826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 243955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 244026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 244154359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 244254359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 244354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 244454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 244554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 244654359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 244754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 244854359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 244954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 245054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 245154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 245254359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 245354359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 245454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 245554359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 245654359294a7c9dc54802d512a5d891a35c1663392caryclark } 245754359294a7c9dc54802d512a5d891a35c1663392caryclark } 245854359294a7c9dc54802d512a5d891a35c1663392caryclark } 245954359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 246054359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 246154359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 246254359294a7c9dc54802d512a5d891a35c1663392caryclark} 246354359294a7c9dc54802d512a5d891a35c1663392caryclark 2464ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 246555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd() 2466ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 246755888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoinEnd(coin)) { 246855888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoinEnd(this)); 246955888e44171ffd48b591d19256884a969fe4da17caryclark return; 247055888e44171ffd48b591d19256884a969fe4da17caryclark } 247155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 247255888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2473ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinEnd_Glitch, this, coin); 247455888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoinEnd = this->fCoinEnd; 247555888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoinEnd = coinNext; 247655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 247755888e44171ffd48b591d19256884a969fe4da17caryclark} 247855888e44171ffd48b591d19256884a969fe4da17caryclark 247930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with mergeMatches() 248030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Look to see if pt-t linked list contains same segment more than once 248130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if so, and if each pt-t is directly pointed to by spans in that segment, 248230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// merge them 248330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// keep the points, but remove spans so that the segment doesn't have 2 or more 248430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// spans pointing to the same pt-t loop at different loop elements 2485ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpanBase::debugMergeMatches(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 248630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* test = &fPtT; 248730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* testNext; 248830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* stop = test; 248930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 249030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark testNext = test->next(); 249130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (test->deleted()) { 249230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 249330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 249430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* testBase = test->span(); 249530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(testBase->ptT() == test); 249630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* segment = test->segment(); 249730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (segment->done()) { 249830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 249930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* inner = opp->ptT(); 250130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* innerStop = inner; 250230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 250330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->segment() != segment) { 250430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 250530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->deleted()) { 250730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 250830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 250930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* innerBase = inner->span(); 251030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(innerBase->ptT() == inner); 251130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // when the intersection is first detected, the span base is marked if there are 251230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // more than one point in the intersection. 251330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) { 251430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(inner->fT)) { 2515ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, innerBase, test); 251630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 251730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(inner->fT != test->fT); 251830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(test->fT)) { 2519ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, testBase, inner); 252030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 2521ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMergeMatches_Glitch, segment); 252230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(testBase->debugSetDeleted()); 252330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// test->setDeleted(); 252430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(innerBase->debugSetDeleted()); 252530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// inner->setDeleted(); 252630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 252730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 252830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#ifdef SK_DEBUG // assert if another undeleted entry points to segment 252930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* debugInner = inner; 253030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark while ((debugInner = debugInner->next()) != innerStop) { 253130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->segment() != segment) { 253230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 253330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 253430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->deleted()) { 253530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 253630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 253730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkOPASSERT(0); 253830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 253930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#endif 254030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 254130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// } 254230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 254330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((inner = inner->next()) != innerStop); 254430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((test = testNext) != stop); 2545ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark this->debugCheckForCollapsedCoincidence(log); 254630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 254730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 254855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 254926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2550025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugResetCoinT() const { 2551025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2552025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2553025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2554025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugResetCoinT(); 2555025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2556025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2557025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2558025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2559025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2560025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugSetCoinT(int index) const { 2561025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2562025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2563025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2564025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (!ptT->deleted()) { 2565025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugSetCoinT(index); 2566025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2567025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2568025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2569025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2570025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2571025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 257226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 257326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 257426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 257526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 257626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 257726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 257826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 257926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 258026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 258126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 258226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 258326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 258426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 258554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 258655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 258755888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 258855888e44171ffd48b591d19256884a969fe4da17caryclark return; 258955888e44171ffd48b591d19256884a969fe4da17caryclark } 259055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 259154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 259254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 259354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 259454359294a7c9dc54802d512a5d891a35c1663392caryclark do { 259554359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 259654359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 259754359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 259854359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 259954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 260054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 260154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 260254359294a7c9dc54802d512a5d891a35c1663392caryclark } 260354359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 260454359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 260554359294a7c9dc54802d512a5d891a35c1663392caryclark } 260654359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 260754359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 260854359294a7c9dc54802d512a5d891a35c1663392caryclark } 26094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 261054359294a7c9dc54802d512a5d891a35c1663392caryclark} 261154359294a7c9dc54802d512a5d891a35c1663392caryclark 261254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 261354359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 261454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 261554359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 261654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 261754359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 261854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 261954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 262054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 262154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 262254359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 262354359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 262454359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 262554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 262654359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 262754359294a7c9dc54802d512a5d891a35c1663392caryclark } 262854359294a7c9dc54802d512a5d891a35c1663392caryclark } 262954359294a7c9dc54802d512a5d891a35c1663392caryclark } 263054359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 263154359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 263254359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 263354359294a7c9dc54802d512a5d891a35c1663392caryclark} 263454359294a7c9dc54802d512a5d891a35c1663392caryclark 2635ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 263655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header 2637ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 263855888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoincidence(coin)) { 263955888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoincidence(this)); 264055888e44171ffd48b591d19256884a969fe4da17caryclark return; 264155888e44171ffd48b591d19256884a969fe4da17caryclark } 264255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 264355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 2644ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinStart_Glitch, this, coin); 264555888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoincident = this->fCoincident; 264655888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoincident = coinNext; 264755888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 264855888e44171ffd48b591d19256884a969fe4da17caryclark} 264955888e44171ffd48b591d19256884a969fe4da17caryclark 265055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() 2651ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clarkvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped, bool ordered) const { 265255888e44171ffd48b591d19256884a969fe4da17caryclark if (this->containsCoincidence(segment)) { 265355888e44171ffd48b591d19256884a969fe4da17caryclark return; 265455888e44171ffd48b591d19256884a969fe4da17caryclark } 265555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* next = &fPtT; 265655888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->next()) != &fPtT) { 265755888e44171ffd48b591d19256884a969fe4da17caryclark if (next->segment() == segment) { 2658ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpan* span; 2659ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* base = next->span(); 2660ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (!ordered) { 2661ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpSpanBase* spanEnd = fNext->contains(segment)->span(); 2662ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT()); 2663ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!start->span()->upCastable(), this); 2664ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = const_cast<SkOpSpan*>(start->span()->upCast()); 2665ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2666ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else if (flipped) { 2667ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->prev(); 2668ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!span, this); 2669ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2670ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark else { 2671ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark FAIL_IF(!base->upCastable(), this); 2672ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark span = base->upCast(); 2673ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark } 2674ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinInsert_Glitch, span); 267555888e44171ffd48b591d19256884a969fe4da17caryclark return; 267655888e44171ffd48b591d19256884a969fe4da17caryclark } 267755888e44171ffd48b591d19256884a969fe4da17caryclark } 2678ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark#if DEBUG_COIN 2679ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark log->record(SkPathOpsDebug::kMarkCoinMissing_Glitch, segment, this); 268055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 2681ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark return; 268255888e44171ffd48b591d19256884a969fe4da17caryclark} 268355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 268455888e44171ffd48b591d19256884a969fe4da17caryclark 2685624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 2686624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 2687624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 2688624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 2689624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 2690624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2691624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 2692624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 2693624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 2694624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 2695624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 2696624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2697624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 2698624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 2699624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 2700624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2701624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 2702624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2703624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 2704624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 2705624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2706624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 270754359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 270854359294a7c9dc54802d512a5d891a35c1663392caryclark 270955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp() 271029b2563afb1677515739f1d24fb27733626eca92caryclarkvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { 271129b2563afb1677515739f1d24fb27733626eca92caryclark SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); 271255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(this != opp); 271355888e44171ffd48b591d19256884a969fe4da17caryclark// this->fNext = opp; 271429b2563afb1677515739f1d24fb27733626eca92caryclark SkASSERT(oppPrev != oldNext); 271555888e44171ffd48b591d19256884a969fe4da17caryclark// oppPrev->fNext = oldNext; 271655888e44171ffd48b591d19256884a969fe4da17caryclark} 271755888e44171ffd48b591d19256884a969fe4da17caryclark 271826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 271926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 272026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 272126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 272226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 272326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 272426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 272526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 272626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 272726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 272826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 272926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 273026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 273126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 273226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 273426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 273526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 273626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 273726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 273826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 273926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 274026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 274126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 274226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 274326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 274426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 274526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 274626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 274726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 274826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 274926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 275026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 275126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 275226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 275326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 275426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 275526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 275626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 275726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 27588016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclarkconst SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const { 27598016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark return fT < end->fT ? end : this; 27608016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark} 27618016b264ceec2b11d2acbeb77a9fbe66e48368b9caryclark 276254359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 276354359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 276454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 276554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 276654359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 276754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 276854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 276954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 277054359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 277154359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 277254359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 277354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 277454359294a7c9dc54802d512a5d891a35c1663392caryclark } 277554359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 277654359294a7c9dc54802d512a5d891a35c1663392caryclark } 27774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 27784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 277926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 278026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 278126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 278226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 278326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 278426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 278526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 278654359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 278754359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 278854359294a7c9dc54802d512a5d891a35c1663392caryclark} 278954359294a7c9dc54802d512a5d891a35c1663392caryclark 279029b2563afb1677515739f1d24fb27733626eca92caryclarkconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { 279129b2563afb1677515739f1d24fb27733626eca92caryclark return this->oppPrev(const_cast<SkOpPtT*>(opp)); 279229b2563afb1677515739f1d24fb27733626eca92caryclark} 279329b2563afb1677515739f1d24fb27733626eca92caryclark 2794025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugResetCoinT() const { 2795025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2796025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugResetCoinT(); 2797025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2798025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2799025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2800025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugSetCoinT(int index) const { 2801025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2802025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugSetCoinT(index, fT); 2803025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2804025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2805025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 280654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 280755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 280855888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 280955888e44171ffd48b591d19256884a969fe4da17caryclark return; 281055888e44171ffd48b591d19256884a969fe4da17caryclark } 281155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 281254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 2813ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark SkOpPhase phase = contour()->globalState()->phase(); 2814ab87d7abf1df007c90bef2e916294ca325d81c81Cary Clark if (phase == SkOpPhase::kIntersecting || phase == SkOpPhase::kFixWinding) { 281554359294a7c9dc54802d512a5d891a35c1663392caryclark return; 28164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 281754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 281854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 281954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 282054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 28214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 28224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 28231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28241049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 28251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 28261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 28271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 28281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 28291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 28301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 28311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 28321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 28331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 28341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 28361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 28371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28401049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 28411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 28421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 28431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 28451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 28461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 28471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28511049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 28521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 28531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 28541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 28551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 28561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 28571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 28581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 28591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 28611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 28621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 28631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 28641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 28671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 28681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 28721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 28731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 28741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 28751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 28771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 28781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 28791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 28801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 28821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 28831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 28841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 28851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 28861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 28871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 28891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 28901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28911049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 28921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 28931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 28941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 28951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 28961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 28971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 28981049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 28991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 29001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 29011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 290296fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 29031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 29041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 29051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 29061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 29071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 29081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 29091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 29101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 29111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 29121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 29131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 29141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 29151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 29161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 29171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 29181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 29191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 29201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 29211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 29221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 29231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 29241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 29251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 29261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 29271326068147ee60de138061a3fc1157fcfd5d017bcaryclark 2928918fb1fe6ff5349a2d1e5fb6872139f5fb931480Cary Clark#if DEBUG_DUMP_VERIFY 29291326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkData.h" 29301326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkStream.h" 29311326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29321326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) { 29331326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDynamicMemoryWStream wStream; 29341326068147ee60de138061a3fc1157fcfd5d017bcaryclark path.dump(&wStream, force, dumpAsHex); 29351326068147ee60de138061a3fc1157fcfd5d017bcaryclark sk_sp<SkData> data(wStream.detachAsData()); 29361326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data()); 29371326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29381326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29391326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int dumpID = 0; 29401326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29411326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(const SkPath& one, const SkPath& two, SkPathOp op, 29421326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* testName) { 29431326068147ee60de138061a3fc1157fcfd5d017bcaryclark FILE* file = sk_fopen("op_dump.txt", kWrite_SkFILE_Flag); 29441326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(file, one, two, op, testName); 29451326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29461326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29471326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op, 29481326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* testName) { 29491326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* name = testName ? testName : "op"; 29501326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, 29511326068147ee60de138061a3fc1157fcfd5d017bcaryclark "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 29521326068147ee60de138061a3fc1157fcfd5d017bcaryclark name, ++dumpID); 29531326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path;\n"); 29541326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType()); 29551326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, one, false, true); 29561326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path1(path);\n"); 29571326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.reset();\n"); 29581326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType()); 29591326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, two, false, true); 29601326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path2(path);\n"); 29611326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op); 29621326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "}\n\n"); 29631326068147ee60de138061a3fc1157fcfd5d017bcaryclark fclose(file); 29641326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29651326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29661326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(const SkPath& path, const char* testName) { 29671326068147ee60de138061a3fc1157fcfd5d017bcaryclark FILE* file = sk_fopen("simplify_dump.txt", kWrite_SkFILE_Flag); 29681326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(file, path, testName); 29691326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29701326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29711326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::DumpSimplify(FILE* file, const SkPath& path, const char* testName) { 29721326068147ee60de138061a3fc1157fcfd5d017bcaryclark const char* name = testName ? testName : "simplify"; 29731326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, 29741326068147ee60de138061a3fc1157fcfd5d017bcaryclark "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 29751326068147ee60de138061a3fc1157fcfd5d017bcaryclark name, ++dumpID); 29761326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " SkPath path;\n"); 29771326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", path.getFillType()); 29781326068147ee60de138061a3fc1157fcfd5d017bcaryclark dump_path(file, path, false, true); 29791326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, " testSimplify(reporter, path, filename);\n"); 29801326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(file, "}\n\n"); 29811326068147ee60de138061a3fc1157fcfd5d017bcaryclark fclose(file); 29821326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 29831326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29841326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkBitmap.h" 29851326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkCanvas.h" 29861326068147ee60de138061a3fc1157fcfd5d017bcaryclark#include "SkPaint.h" 29871326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29881326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitWidth = 64; 29891326068147ee60de138061a3fc1157fcfd5d017bcaryclarkconst int bitHeight = 64; 29901326068147ee60de138061a3fc1157fcfd5d017bcaryclark 29911326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic void debug_scale_matrix(const SkPath& one, const SkPath* two, SkMatrix& scale) { 29921326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRect larger = one.getBounds(); 29931326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (two) { 29941326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.join(two->getBounds()); 29951326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 29961326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar largerWidth = larger.width(); 29971326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (largerWidth < 4) { 29981326068147ee60de138061a3fc1157fcfd5d017bcaryclark largerWidth = 4; 29991326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30001326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar largerHeight = larger.height(); 30011326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (largerHeight < 4) { 30021326068147ee60de138061a3fc1157fcfd5d017bcaryclark largerHeight = 4; 30031326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30041326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar hScale = (bitWidth - 2) / largerWidth; 30051326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar vScale = (bitHeight - 2) / largerHeight; 30061326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.reset(); 30071326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.preScale(hScale, vScale); 30081326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fLeft *= hScale; 30091326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fRight *= hScale; 30101326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fTop *= vScale; 30111326068147ee60de138061a3fc1157fcfd5d017bcaryclark larger.fBottom *= vScale; 30121326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft 30131326068147ee60de138061a3fc1157fcfd5d017bcaryclark : 16000 < larger.fRight ? 16000 - larger.fRight : 0; 30141326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop 30151326068147ee60de138061a3fc1157fcfd5d017bcaryclark : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0; 30161326068147ee60de138061a3fc1157fcfd5d017bcaryclark scale.preTranslate(dx, dy); 30171326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30181326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30191326068147ee60de138061a3fc1157fcfd5d017bcaryclarkstatic int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) { 30201326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (bits.width() == 0) { 30211326068147ee60de138061a3fc1157fcfd5d017bcaryclark bits.allocN32Pixels(bitWidth * 2, bitHeight); 30221326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30231326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkCanvas canvas(bits); 30241326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawColor(SK_ColorWHITE); 30251326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPaint paint; 30261326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.save(); 30271326068147ee60de138061a3fc1157fcfd5d017bcaryclark const SkRect& bounds1 = one.getBounds(); 30281326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); 30291326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawPath(one, paint); 30301326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.restore(); 30311326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.save(); 30321326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1); 30331326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.drawPath(two, paint); 30341326068147ee60de138061a3fc1157fcfd5d017bcaryclark canvas.restore(); 30351326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = 0; 30361326068147ee60de138061a3fc1157fcfd5d017bcaryclark for (int y = 0; y < bitHeight - 1; ++y) { 30371326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr1 = bits.getAddr32(0, y); 30381326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr2 = bits.getAddr32(0, y + 1); 30391326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr3 = bits.getAddr32(bitWidth, y); 30401326068147ee60de138061a3fc1157fcfd5d017bcaryclark uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1); 30411326068147ee60de138061a3fc1157fcfd5d017bcaryclark for (int x = 0; x < bitWidth - 1; ++x) { 30421326068147ee60de138061a3fc1157fcfd5d017bcaryclark // count 2x2 blocks 30431326068147ee60de138061a3fc1157fcfd5d017bcaryclark bool err = addr1[x] != addr3[x]; 30441326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (err) { 30451326068147ee60de138061a3fc1157fcfd5d017bcaryclark errors += addr1[x + 1] != addr3[x + 1] 30461326068147ee60de138061a3fc1157fcfd5d017bcaryclark && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1]; 30471326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30481326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30491326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30501326068147ee60de138061a3fc1157fcfd5d017bcaryclark return errors; 30511326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30521326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30531326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op) { 30541326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDebugf("// Op did not expect failure\n"); 30551326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(stderr, one, two, op, "opTest"); 30561326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30571326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30581326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30591326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op, 30601326068147ee60de138061a3fc1157fcfd5d017bcaryclark const SkPath& result) { 30611326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath pathOut, scaledPathOut; 30621326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion rgnA, rgnB, openClip, rgnOut; 30631326068147ee60de138061a3fc1157fcfd5d017bcaryclark openClip.setRect(-16000, -16000, 16000, 16000); 30641326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnA.setPath(one, openClip); 30651326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnB.setPath(two, openClip); 30661326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.op(rgnA, rgnB, (SkRegion::Op) op); 30671326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.getBoundaryPath(&pathOut); 30681326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkMatrix scale; 30691326068147ee60de138061a3fc1157fcfd5d017bcaryclark debug_scale_matrix(one, &two, scale); 30701326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; 30711326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledA, scaledB; 30721326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.addPath(one, scale); 30731326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.setFillType(one.getFillType()); 30741326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledB.addPath(two, scale); 30751326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledB.setFillType(two.getFillType()); 30761326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.setPath(scaledA, openClip); 30771326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnB.setPath(scaledB, openClip); 30781326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op); 30791326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnOut.getBoundaryPath(&scaledPathOut); 30801326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkBitmap bitmap; 30811326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledOut; 30821326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.addPath(result, scale); 30831326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.setFillType(result.getFillType()); 30841326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 30851326068147ee60de138061a3fc1157fcfd5d017bcaryclark const int MAX_ERRORS = 9; 30861326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (errors > MAX_ERRORS) { 30871326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(stderr, "// Op did not expect errors=%d\n", errors); 30881326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpOp(stderr, one, two, op, "opTest"); 30891326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30901326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 30911326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30921326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30931326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::ReportSimplifyFail(const SkPath& path) { 30941326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkDebugf("// Simplify did not expect failure\n"); 30951326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(stderr, path, "simplifyTest"); 30961326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 30971326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 30981326068147ee60de138061a3fc1157fcfd5d017bcaryclark 30991326068147ee60de138061a3fc1157fcfd5d017bcaryclarkvoid SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) { 31001326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath pathOut, scaledPathOut; 31011326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion rgnA, openClip, rgnOut; 31021326068147ee60de138061a3fc1157fcfd5d017bcaryclark openClip.setRect(-16000, -16000, 16000, 16000); 31031326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnA.setPath(path, openClip); 31041326068147ee60de138061a3fc1157fcfd5d017bcaryclark rgnOut.getBoundaryPath(&pathOut); 31051326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkMatrix scale; 31061326068147ee60de138061a3fc1157fcfd5d017bcaryclark debug_scale_matrix(path, nullptr, scale); 31071326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkRegion scaledRgnA; 31081326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledA; 31091326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.addPath(path, scale); 31101326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledA.setFillType(path.getFillType()); 31111326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.setPath(scaledA, openClip); 31121326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledRgnA.getBoundaryPath(&scaledPathOut); 31131326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkBitmap bitmap; 31141326068147ee60de138061a3fc1157fcfd5d017bcaryclark SkPath scaledOut; 31151326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.addPath(result, scale); 31161326068147ee60de138061a3fc1157fcfd5d017bcaryclark scaledOut.setFillType(result.getFillType()); 31171326068147ee60de138061a3fc1157fcfd5d017bcaryclark int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 31181326068147ee60de138061a3fc1157fcfd5d017bcaryclark const int MAX_ERRORS = 9; 31191326068147ee60de138061a3fc1157fcfd5d017bcaryclark if (errors > MAX_ERRORS) { 31201326068147ee60de138061a3fc1157fcfd5d017bcaryclark fprintf(stderr, "// Simplify did not expect errors=%d\n", errors); 31211326068147ee60de138061a3fc1157fcfd5d017bcaryclark DumpSimplify(stderr, path, "simplifyTest"); 31221326068147ee60de138061a3fc1157fcfd5d017bcaryclark fflush(stderr); 31231326068147ee60de138061a3fc1157fcfd5d017bcaryclark } 31241326068147ee60de138061a3fc1157fcfd5d017bcaryclark} 31251326068147ee60de138061a3fc1157fcfd5d017bcaryclark 31261326068147ee60de138061a3fc1157fcfd5d017bcaryclark#endif 3127