SkPathOpsDebug.cpp revision 30b9fdd6a1d607bde20c793af65b5e2e8a1737ca
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc. 307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * 407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file. 607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h" 926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h" 1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h" 1102802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h" 121b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h" 1354359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h" 1454359294a7c9dc54802d512a5d891a35c1663392caryclark 1530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_IF 1630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_IF(cond, coin) \ 1730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false) 1830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 1930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef FAIL_WITH_NULL_IF 2030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define FAIL_WITH_NULL_IF(cond, span) \ 2130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while (false) 2230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#undef RETURN_FALSE_IF 2430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#define RETURN_FALSE_IF(cond, span) \ 2530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while (false) 2630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 2755888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans; 2826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 3054359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail; 3154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 33624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 34624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 35624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 36624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 37624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 38624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 39624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 40624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 41624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 44570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 458cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 46fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 47fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 48570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 5054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 5254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 6155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 6226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkenum GlitchType { 6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddCorruptCoin_Glitch, 6426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddExpandedCoin_Glitch, 6555888e44171ffd48b591d19256884a969fe4da17caryclark kAddExpandedFail_Glitch, 6655888e44171ffd48b591d19256884a969fe4da17caryclark kAddIfMissingCoin_Glitch, 6726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddMissingCoin_Glitch, 6855888e44171ffd48b591d19256884a969fe4da17caryclark kAddMissingExtend_Glitch, 6955888e44171ffd48b591d19256884a969fe4da17caryclark kAddOrOverlap_Glitch, 7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedCoin_Glitch, 7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedDone_Glitch, 7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedOppValue_Glitch, 7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedSpan_Glitch, 7426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedWindValue_Glitch, 7526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kDeletedCoin_Glitch, 7626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kExpandCoin_Glitch, 7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinEnd_Glitch, 7826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinInsert_Glitch, 7955888e44171ffd48b591d19256884a969fe4da17caryclark kMarkCoinMissing_Glitch, 8055888e44171ffd48b591d19256884a969fe4da17caryclark kMarkCoinStart_Glitch, 8155888e44171ffd48b591d19256884a969fe4da17caryclark kMergeContained_Glitch, 8230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark kMergeMatches_Glitch, 8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingCoin_Glitch, 8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingDone_Glitch, 8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingIntersection_Glitch, 8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMoveMultiple_Glitch, 8755888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyClearAll_Glitch, 8855888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyClearAll2_Glitch, 8955888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyMerge_Glitch, 9055888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyMergeFinal_Glitch, 9155888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyRelease_Glitch, 9255888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyReleaseFinal_Glitch, 9355888e44171ffd48b591d19256884a969fe4da17caryclark kReleasedSpan_Glitch, 9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnaligned_Glitch, 9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedHead_Glitch, 9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedTail_Glitch, 9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 9826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9955888e44171ffd48b591d19256884a969fe4da17caryclarkstatic const int kGlitchType_Count = kUnalignedTail_Glitch + 1; 10026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 10126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* fStage; 10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 10655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* fOppSegment; 10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 11155888e44171ffd48b591d19256884a969fe4da17caryclark double fStartT; 11255888e44171ffd48b591d19256884a969fe4da17caryclark double fEndT; 11355888e44171ffd48b591d19256884a969fe4da17caryclark double fOppStartT; 11455888e44171ffd48b591d19256884a969fe4da17caryclark double fOppEndT; 11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchType fType; 11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 11926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* recordCommon(GlitchType type, const char* stage) { 12126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fStage = stage; 12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 12655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = nullptr; 12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 12826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 12926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 13026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 13155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = SK_ScalarNaN; 13255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = SK_ScalarNaN; 13355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = SK_ScalarNaN; 13455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = SK_ScalarNaN; 13526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 13626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 13726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 13826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 13926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 14026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 14226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 14626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 14755888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 14855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 14955888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 15055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 15155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = ptT; 15255888e44171ffd48b591d19256884a969fe4da17caryclark } 15355888e44171ffd48b591d19256884a969fe4da17caryclark 15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 15555888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* opp = NULL) { 15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 15755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 15855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 15955888e44171ffd48b591d19256884a969fe4da17caryclark if (opp) { 16055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = opp->coinPtTStart(); 16155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = opp->coinPtTEnd(); 16255888e44171ffd48b591d19256884a969fe4da17caryclark } 16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 16526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 16626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 16926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 17055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 17226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 17426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, double t, 17526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 17626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 17855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 18326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 18555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 18655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 18855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = coinSpan; 18955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = endSpan; 19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 19126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 19355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* base) { 19426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 19555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 19655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 19755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 19826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 19926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 20026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 20126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 20226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 20326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 20426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 20526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 20626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 20726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 20826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 20955888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg, double startT, 21055888e44171ffd48b591d19256884a969fe4da17caryclark double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 21155888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 21255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 21355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = startT; 21455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = endT; 21555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = oppSeg; 21655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = oppStartT; 21755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = oppEndT; 21855888e44171ffd48b591d19256884a969fe4da17caryclark } 21955888e44171ffd48b591d19256884a969fe4da17caryclark 22055888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg, 22155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span) { 22255888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 22355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 22455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 22555888e44171ffd48b591d19256884a969fe4da17caryclark } 22655888e44171ffd48b591d19256884a969fe4da17caryclark 22755888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, double t, const SkOpSpanBase* span) { 22855888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 22955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 23055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 23155888e44171ffd48b591d19256884a969fe4da17caryclark } 23255888e44171ffd48b591d19256884a969fe4da17caryclark 23355888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg) { 23455888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 23555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 23655888e44171ffd48b591d19256884a969fe4da17caryclark } 23755888e44171ffd48b591d19256884a969fe4da17caryclark 23855888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 23955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 24055888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 24155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 24255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = ptT; 24355888e44171ffd48b591d19256884a969fe4da17caryclark } 24455888e44171ffd48b591d19256884a969fe4da17caryclark 24526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 24626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 24755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 24826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 24955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 25055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 25155888e44171ffd48b591d19256884a969fe4da17caryclark SkOpContour* contour = contourList; 25255888e44171ffd48b591d19256884a969fe4da17caryclark do { 25355888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugShowActiveSpans(); 25455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((contour = contour->next())); 25555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 25655888e44171ffd48b591d19256884a969fe4da17caryclark} 25755888e44171ffd48b591d19256884a969fe4da17caryclark 25855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 25926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { 26055888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(true); 26155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 26226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 26326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 26426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 26555888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugCheckValid(id, &glitches); // don't call validate; spans may be inconsistent 26626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 26726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark contour->debugCheckHealth(id, &glitches); 26855888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugMissingCoincidence(id, &glitches); 26926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 27055888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugRemoveCollapsed(id, &glitches); 27126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddMissing(id, &glitches); 27226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugExpand(id, &glitches); 27326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddExpanded(id, &glitches); 27426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugMark(id, &glitches); 27555888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugReorder(id, &glitches); 27626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 27726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 27826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 27926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 28026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 28126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 28226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 28326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 28426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(" %s\n", id); 28555888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 28655888e44171ffd48b591d19256884a969fe4da17caryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 28755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%02d: ", index); 28855888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fBase) { 28955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" base=%d", glitch.fBase->debugID()); 29055888e44171ffd48b591d19256884a969fe4da17caryclark } 29155888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSuspect) { 29255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" base=%d", glitch.fSuspect->debugID()); 29355888e44171ffd48b591d19256884a969fe4da17caryclark } 29455888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSegment) { 29555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fSegment->debugID()); 29655888e44171ffd48b591d19256884a969fe4da17caryclark } 29755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fCoinSpan) { 29855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" coinSpan=%d", glitch.fCoinSpan->debugID()); 29955888e44171ffd48b591d19256884a969fe4da17caryclark } 30055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fEndSpan) { 30155888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 30255888e44171ffd48b591d19256884a969fe4da17caryclark } 30355888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSpan) { 30455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppSpan=%d", glitch.fOppSpan->debugID()); 30555888e44171ffd48b591d19256884a969fe4da17caryclark } 30655888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppEndSpan) { 30755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 30855888e44171ffd48b591d19256884a969fe4da17caryclark } 30955888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fStartT)) { 31055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" startT=%g", glitch.fStartT); 31155888e44171ffd48b591d19256884a969fe4da17caryclark } 31255888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fEndT)) { 31355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endT=%g", glitch.fEndT); 31455888e44171ffd48b591d19256884a969fe4da17caryclark } 31555888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSegment) { 31655888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 31755888e44171ffd48b591d19256884a969fe4da17caryclark } 31855888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppStartT)) { 31955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppStartT=%g", glitch.fOppStartT); 32055888e44171ffd48b591d19256884a969fe4da17caryclark } 32155888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppEndT)) { 32255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndT=%g", glitch.fOppEndT); 32355888e44171ffd48b591d19256884a969fe4da17caryclark } 32455888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 32555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 32655888e44171ffd48b591d19256884a969fe4da17caryclark } 32755888e44171ffd48b591d19256884a969fe4da17caryclark switch (glitch.fType) { 32855888e44171ffd48b591d19256884a969fe4da17caryclark case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 32955888e44171ffd48b591d19256884a969fe4da17caryclark case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 33055888e44171ffd48b591d19256884a969fe4da17caryclark case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 33155888e44171ffd48b591d19256884a969fe4da17caryclark case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 33255888e44171ffd48b591d19256884a969fe4da17caryclark case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 33355888e44171ffd48b591d19256884a969fe4da17caryclark case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 33455888e44171ffd48b591d19256884a969fe4da17caryclark case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 33555888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 33655888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 33755888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 33855888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 33955888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 34055888e44171ffd48b591d19256884a969fe4da17caryclark case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 34155888e44171ffd48b591d19256884a969fe4da17caryclark case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 34255888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 34355888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 34455888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 34555888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 34655888e44171ffd48b591d19256884a969fe4da17caryclark case kMergeContained_Glitch: SkDebugf(" MergeContained"); break; 34730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; 34855888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 34955888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 35055888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 35155888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 35255888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 35355888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 35455888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 35555888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 35655888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 35755888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 35855888e44171ffd48b591d19256884a969fe4da17caryclark case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 35955888e44171ffd48b591d19256884a969fe4da17caryclark case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 36055888e44171ffd48b591d19256884a969fe4da17caryclark case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 36155888e44171ffd48b591d19256884a969fe4da17caryclark case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 36255888e44171ffd48b591d19256884a969fe4da17caryclark default: SkASSERT(0); 36355888e44171ffd48b591d19256884a969fe4da17caryclark } 36455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("\n"); 36555888e44171ffd48b591d19256884a969fe4da17caryclark } 36655888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(false); 36755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 36855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("active after %s:\n", id); 36955888e44171ffd48b591d19256884a969fe4da17caryclark ShowActiveSpans(contourList); 37055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 37155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 37226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 37326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 3744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 37526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 376570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 37707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 37807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 37907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 38007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 38307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 38507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 38607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 38707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 38807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 38907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 39007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 39107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 39207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 393570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 39507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 39607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 397570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 39807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 39907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 40007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 40107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 40207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 40307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 40454359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 40554359294a7c9dc54802d512a5d891a35c1663392caryclark 406a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 40707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 408385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 409cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 410385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 411a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 412570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 41307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 41407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 41507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 41607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 41707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 41807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 41907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 42007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 42107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 42207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 42307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 42407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 42507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 426a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 427a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 428570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4291049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 4301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 4311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 4321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 4331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 4341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 4351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 4361049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 4371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 4381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 4391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 44055888e44171ffd48b591d19256884a969fe4da17caryclark "kXOR_PathOp", 4411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 4421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 4431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 44403b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 44503b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 44603b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 44703b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 4481049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 4491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 4501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 4511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 4521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 453086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex); 4541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 4551049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 4561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 4571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 4581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 4591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 4601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 4611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 4624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 46427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 46526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 46626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 46826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 46926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 47026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 47126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 47226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 47326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 47426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 47526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 47626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 47726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 47826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 47926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 48026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 48126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 48326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 48426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 48526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 48626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 48826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 48926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 49026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 49126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 49226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 49326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 49426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 49526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 49626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 49726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 49826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 49926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 50026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 50126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 50226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 50326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 50426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 50526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 50626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 50726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 50826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 50926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 51126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 51226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 51326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 51426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 51526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 51626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 51726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 52026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 52126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 52226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 52326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 52426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 52526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 52626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 52926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 53026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 53126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 53226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 53326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 53426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 53526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 53626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 53726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 53826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 53926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 54026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 54126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 54226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 54326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 54426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 54526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 54626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 54726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 54826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 54926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 55027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 55127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG 55227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const { 55327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE 55427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return FLAGS_runFail; 55527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else 55627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 55727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 55827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 55927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 56027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 56126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 56226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 56326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 56426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 56526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 56626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 56726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 56826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 56926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 57026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 57126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 575624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 576624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsQuad.h" 577624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 578624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 579624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 580624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 581624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 582624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 583624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 584624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 585624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 586624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 587624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 588624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 589624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 590ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 591ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 592ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 593ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 5944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 595570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 596570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 59730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE 59855888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT() 59930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* SkOpSegment::debugAddT(double t, const char* id, SkPathOpsDebug::GlitchLog* log) const { 60055888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 60155888e44171ffd48b591d19256884a969fe4da17caryclark SkPoint pt = this->ptAtT(t); 60255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* span = &fHead; 60326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 60455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* result = span->ptT(); 60529b2563afb1677515739f1d24fb27733626eca92caryclark if (t == result->fT || this->match(result, this, t, pt)) { 60655888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 607ef4f32ac858825dc443cfe4739ea878fb0bf550fcaryclark return result; 60855888e44171ffd48b591d19256884a969fe4da17caryclark } 60955888e44171ffd48b591d19256884a969fe4da17caryclark if (t < result->fT) { 61055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = result->span()->prev(); 61130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(!prev, span); 61229b2563afb1677515739f1d24fb27733626eca92caryclark // marks in global state that new op span has been allocated 61329b2563afb1677515739f1d24fb27733626eca92caryclark this->globalState()->setAllocatedOpSpan(); 61455888e44171ffd48b591d19256884a969fe4da17caryclark// span->init(this, prev, t, pt); 61555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 61655888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 61755888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 61855888e44171ffd48b591d19256884a969fe4da17caryclark// span->segment()->debugID(), span->debugID()); 61955888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 62055888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 62155888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 62255888e44171ffd48b591d19256884a969fe4da17caryclark } 62330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_WITH_NULL_IF(span != &fTail, span); 62455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->upCast()->next())); 62555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 62629b2563afb1677515739f1d24fb27733626eca92caryclark return nullptr; // we never get here, but need this to satisfy compiler 62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 63655888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 64455888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 65155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveMultiples(id, glitches); 65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveNearby(id, glitches); 65655888e44171ffd48b591d19256884a969fe4da17caryclark debugMissingCoincidence(id, glitches); 65755888e44171ffd48b591d19256884a969fe4da17caryclark} 65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 65955888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll() 66055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearAll(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 66155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span = &fHead; 66255888e44171ffd48b591d19256884a969fe4da17caryclark do { 66355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugClearOne(span, id, glitches); 66455888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->next()->upCastable())); 66555888e44171ffd48b591d19256884a969fe4da17caryclark this->globalState()->coincidence()->debugRelease(id, glitches, this); 66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 66726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 66855888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne() 66955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 67055888e44171ffd48b591d19256884a969fe4da17caryclark if (span->windValue()) glitches->record(kCollapsedWindValue_Glitch, id, span); 67155888e44171ffd48b591d19256884a969fe4da17caryclark if (span->oppValue()) glitches->record(kCollapsedOppValue_Glitch, id, span); 67255888e44171ffd48b591d19256884a969fe4da17caryclark if (!span->done()) glitches->record(kCollapsedDone_Glitch, id, span); 67326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 67426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 67526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 67654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 67796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 67854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 67954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 68054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 681dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 68254359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 683dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 68454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 685dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 686dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 687dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 688dac1d17027dcaa5596885a9f333979418b35001ccaryclark 68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 69055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited 69155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 69255888e44171ffd48b591d19256884a969fe4da17caryclark // reset visited flag back to false 69355888e44171ffd48b591d19256884a969fe4da17caryclark do { 69455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 69555888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != stopPtT) { 69655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->segment(); 69755888e44171ffd48b591d19256884a969fe4da17caryclark opp->resetDebugVisited(); 69855888e44171ffd48b591d19256884a969fe4da17caryclark } 69955888e44171ffd48b591d19256884a969fe4da17caryclark } while (!span->final() && (span = span->upCast()->next())); 70055888e44171ffd48b591d19256884a969fe4da17caryclark} 70155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 70255888e44171ffd48b591d19256884a969fe4da17caryclark 70355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 70455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence() 70555888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves 70655888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear 70755888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed 70855888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given 70955888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C: 71055888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 71155888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C. 71255888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2, 71355888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B. 71455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 71526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 71626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 71726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 71826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 71926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 72055888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 72126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 72226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 72326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 72426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 72526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 72626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 72726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 72855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->span()->segment(); 72926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 73026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 73126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 73355888e44171ffd48b591d19256884a969fe4da17caryclark if (!opp->debugVisited()) { 73426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 73526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 73726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 73826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73955888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this) { 74055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 74155888e44171ffd48b591d19256884a969fe4da17caryclark } 74226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 74326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 74426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 74555888e44171ffd48b591d19256884a969fe4da17caryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 74626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 74726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 74855888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 74926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75055888e44171ffd48b591d19256884a969fe4da17caryclark } 75126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 75226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 75326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 75426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 75526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 75626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 75726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 75826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 75926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* segment = priorPtT->span()->segment(); 76226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 76326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 76426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 76826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 77126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77355888e44171ffd48b591d19256884a969fe4da17caryclark if (priorPtT == ptT) { 77455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 77555888e44171ffd48b591d19256884a969fe4da17caryclark } 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 78455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 78555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPtT = ptT->span()->ptT(); 78655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 78755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 78855888e44171ffd48b591d19256884a969fe4da17caryclark if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79155888e44171ffd48b591d19256884a969fe4da17caryclark if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 79255888e44171ffd48b591d19256884a969fe4da17caryclark // mark coincidence 79330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#if DEBUG_COINCIDENCE_VERBOSE 79455888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 79555888e44171ffd48b591d19256884a969fe4da17caryclark// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 79655888e44171ffd48b591d19256884a969fe4da17caryclark// rootOppEnd->debugID()); 79755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 79826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, oppEnd); 79955888e44171ffd48b591d19256884a969fe4da17caryclark // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 80055888e44171ffd48b591d19256884a969fe4da17caryclark // } 80155888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 802d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 80355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 80455888e44171ffd48b591d19256884a969fe4da17caryclark // result = true; 80526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 80726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 80826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 80926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 81026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 81126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 81255888e44171ffd48b591d19256884a969fe4da17caryclark DebugClearVisited(&fHead); 81355888e44171ffd48b591d19256884a969fe4da17caryclark return; 81426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 81526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 81655888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples() 81755888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed 81826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 81955888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 82026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 82226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 82326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(addCount >= 1); 82426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (addCount == 1) { 82526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 82626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 82726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 82826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 82926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 83026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 83126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 83226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 83326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 83526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 83626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 83826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 83926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 84026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 84126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 84226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 84326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 84426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 84526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 84626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 84726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 84826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 84926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 85026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 85226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 85326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 85526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 85726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 85826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 85926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 86026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 86126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 87426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 87626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 88126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 88826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 88926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 89326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 89555888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 89630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oppTest->debugMergeMatches(id, glitches, oppSpan); 89730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oppTest->debugAddOpp(id, glitches, oppSpan); 89855888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90155888e44171ffd48b591d19256884a969fe4da17caryclark tryNextSpan: 90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 90555888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan: 90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 90726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 90855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 90955888e44171ffd48b591d19256884a969fe4da17caryclark return; 91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 91255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby() 91355888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 91555888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 91655888e44171ffd48b591d19256884a969fe4da17caryclark // release undeleted spans pointing to this seg that are linked to the primary span 91755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* spanBase = &fHead; 91826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 91955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = spanBase->ptT(); 92055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* headPtT = ptT; 92155888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != headPtT) { 92255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = ptT->span(); 92355888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this && !ptT->deleted() && test != spanBase 92455888e44171ffd48b591d19256884a969fe4da17caryclark && test->ptT() == ptT) { 92555888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 92655888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase == &fHead) { 92755888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyClearAll_Glitch, id, this); 92855888e44171ffd48b591d19256884a969fe4da17caryclark// return; 92955888e44171ffd48b591d19256884a969fe4da17caryclark } 93055888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyReleaseFinal_Glitch, id, spanBase, ptT); 93155888e44171ffd48b591d19256884a969fe4da17caryclark } else if (test->prev()) { 93255888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyRelease_Glitch, id, test, headPtT); 93355888e44171ffd48b591d19256884a969fe4da17caryclark } 93455888e44171ffd48b591d19256884a969fe4da17caryclark// break; 93526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 93626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 93755888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = spanBase->upCast()->next(); 93855888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 93955888e44171ffd48b591d19256884a969fe4da17caryclark 94055888e44171ffd48b591d19256884a969fe4da17caryclark // This loop looks for adjacent spans which are near by 94155888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = &fHead; 94255888e44171ffd48b591d19256884a969fe4da17caryclark do { // iterate through all spans associated with start 94355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = spanBase->upCast()->next(); 94455888e44171ffd48b591d19256884a969fe4da17caryclark if (this->spansNearby(spanBase, test)) { 94555888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 94655888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->prev()) { 94755888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyMergeFinal_Glitch, id, test); 94855888e44171ffd48b591d19256884a969fe4da17caryclark } else { 94955888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyClearAll2_Glitch, id, this); 95055888e44171ffd48b591d19256884a969fe4da17caryclark // return 95155888e44171ffd48b591d19256884a969fe4da17caryclark } 95255888e44171ffd48b591d19256884a969fe4da17caryclark } else { 95355888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyMerge_Glitch, id, spanBase); 95455888e44171ffd48b591d19256884a969fe4da17caryclark } 95555888e44171ffd48b591d19256884a969fe4da17caryclark } 95655888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = test; 95755888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 95855888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 96026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 96126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 9631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 9644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 9654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 966025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 967025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const { 968025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { 969025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = index; 970025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = SkTMin(t, fDebugBaseMin); 971025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = SkTMax(t, fDebugBaseMax); 972025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 973025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 974025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); 975025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (fDebugLastMax < 0 || fDebugLastIndex == index) { 976025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = index; 977025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = SkTMin(t, fDebugLastMin); 978025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = SkTMax(t, fDebugLastMax); 979025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark return; 980025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 981025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); 982025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); 983025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 984025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 985025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 98654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 9874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const { 9884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 9894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 9904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 9914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 9924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 9934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 99454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 99554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 99654359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 9974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 9984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 9991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 10004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 10014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 100354359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 10041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); 100555888e44171ffd48b591d19256884a969fe4da17caryclark // since endpoints may have be adjusted, show actual computed curves 100655888e44171ffd48b591d19256884a969fe4da17caryclark SkDCurve curvePart; 100755888e44171ffd48b591d19256884a969fe4da17caryclark this->subDivide(span, span->next(), &curvePart); 100855888e44171ffd48b591d19256884a969fe4da17caryclark const SkDPoint* pts = curvePart.fCubic.fPts; 100955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 10104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 101155888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 10124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 101455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9gf", curvePart.fConic.fWeight); 10151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 101655888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 101754359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 1018624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=?"); 10194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1020624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=%d", span->windSum()); 1021624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1022624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 1023624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=?"); 1024624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1025624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=%d", span->oppSum()); 1026624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1027624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windValue=%d", span->windValue()); 1028624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 1029624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppValue=%d", span->oppValue()); 10304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 103154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 103254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 10334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 10354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 103654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 103754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 103854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 10391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 10404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 104454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 104554359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 104654359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 10474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 104954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 10504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 105154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 105254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 105354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 105454359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 105554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 105654359294a7c9dc54802d512a5d891a35c1663392caryclark } 105754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 10584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 106054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 10614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 106254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 10631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 10644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 10654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 10664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 10674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 106854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 106954359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 107054359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 107154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 107254359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 107354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 107454359294a7c9dc54802d512a5d891a35c1663392caryclark } 107554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 107654359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 107754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 107854359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 107954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 108054359294a7c9dc54802d512a5d891a35c1663392caryclark } 108154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 108254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 10834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 108554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 10864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 108854359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 10894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 109154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 10924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 109354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 10944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 109554359294a7c9dc54802d512a5d891a35c1663392caryclark 10964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 10974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 109826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 109926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 110026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 110155888e44171ffd48b591d19256884a969fe4da17caryclark This checks the distance between start points; the distance between 110226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 110326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 110426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 110526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 110626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 110726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 110826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 110926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 111026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 111426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 111526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 111626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 111726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 111826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 111926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 112026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 112126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 112226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 112326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 112426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 112526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 112626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 112726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 112826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 112926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 113026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 113126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 113226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 113326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 113426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 113526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 113626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 113726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 113826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 113955888e44171ffd48b591d19256884a969fe4da17caryclark } while (test->fNext != this); 114026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 114126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 114226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 114354359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 114454359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 114554359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 114654359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 114754359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 114854359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart), 114954359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 115054359294a7c9dc54802d512a5d891a35c1663392caryclark break; 115154359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 115254359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart), 115354359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 115454359294a7c9dc54802d512a5d891a35c1663392caryclark break; 11551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 11561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 11571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark CONIC_DEBUG_DATA(fCurvePart, fCurvePart.fConic.fWeight), 11581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 11591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 116054359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 116154359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart), 116254359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 116354359294a7c9dc54802d512a5d891a35c1663392caryclark break; 116454359294a7c9dc54802d512a5d891a35c1663392caryclark default: 116554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 11661b24933e52f50773de29332387a12721811f3012mtklein } 116754359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 116854359294a7c9dc54802d512a5d891a35c1663392caryclark} 116954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 117054359294a7c9dc54802d512a5d891a35c1663392caryclark 1171624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 117254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 117354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 117454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 117554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 117654359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 117754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 117854359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 117954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 118054359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 118154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 118254359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 118354359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 118454359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1185ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1186ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1187ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 118854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 118955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 119055888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 119155888e44171ffd48b591d19256884a969fe4da17caryclark return; 119255888e44171ffd48b591d19256884a969fe4da17caryclark } 119355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 119454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 119554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 119654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 119754359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 119854359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 119954359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 120054359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 120154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 120254359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 120354359294a7c9dc54802d512a5d891a35c1663392caryclark return; 120454359294a7c9dc54802d512a5d891a35c1663392caryclark } 120554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 120654359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 120754359294a7c9dc54802d512a5d891a35c1663392caryclark return; 120854359294a7c9dc54802d512a5d891a35c1663392caryclark } 120954359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 121054359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 121154359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 121254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 121354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 121454359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 121554359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 121654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 121754359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1218624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 121954359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 122054359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 122154359294a7c9dc54802d512a5d891a35c1663392caryclark } 122254359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 122354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 122454359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1225624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 122654359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 122754359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 122854359294a7c9dc54802d512a5d891a35c1663392caryclark } 122954359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 123054359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1231182b499cd75c971f85cdf52c1827b3c220cc9011caryclark SkASSERT(wind == 0 || !FLAGS_runFail); 123254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(opp == 0 || !FLAGS_runFail); 123354359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 123454359294a7c9dc54802d512a5d891a35c1663392caryclark} 123554359294a7c9dc54802d512a5d891a35c1663392caryclark 123654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 123754359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 123854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 123954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 124054359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 124154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1242f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 124354359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 124454359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 124554359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 124654359294a7c9dc54802d512a5d891a35c1663392caryclark break; 124754359294a7c9dc54802d512a5d891a35c1663392caryclark } 1248f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 124954359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 125054359294a7c9dc54802d512a5d891a35c1663392caryclark return; 125154359294a7c9dc54802d512a5d891a35c1663392caryclark } 125254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 125354359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 125454359294a7c9dc54802d512a5d891a35c1663392caryclark} 125554359294a7c9dc54802d512a5d891a35c1663392caryclark 125655888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG 125755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 125855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpGlobalState* debugState) const { 125955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); 126055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); 126155888e44171ffd48b591d19256884a969fe4da17caryclark} 126255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 126455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 126555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */ 126630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// expand the range by checking adjacent spans for coincidence 126755888e44171ffd48b591d19256884a969fe4da17caryclarkbool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const { 126855888e44171ffd48b591d19256884a969fe4da17caryclark bool expanded = false; 126955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = coinPtTStart()->segment(); 127055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSegment = oppPtTStart()->segment(); 127155888e44171ffd48b591d19256884a969fe4da17caryclark do { 127255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coinPtTStart()->span()->upCast(); 127355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = start->prev(); 127455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 127555888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev || !(oppPtT = prev->contains(oppSegment))) { 127655888e44171ffd48b591d19256884a969fe4da17caryclark break; 127755888e44171ffd48b591d19256884a969fe4da17caryclark } 127855888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (prev->t() + start->t()) / 2; 127955888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 128055888e44171ffd48b591d19256884a969fe4da17caryclark break; 128155888e44171ffd48b591d19256884a969fe4da17caryclark } 128255888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT); 128355888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 128455888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 128555888e44171ffd48b591d19256884a969fe4da17caryclark do { 128655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coinPtTEnd()->span(); 128755888e44171ffd48b591d19256884a969fe4da17caryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 128830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (next && next->deleted()) { 128930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 129030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 129155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 129255888e44171ffd48b591d19256884a969fe4da17caryclark if (!next || !(oppPtT = next->contains(oppSegment))) { 129355888e44171ffd48b591d19256884a969fe4da17caryclark break; 129455888e44171ffd48b591d19256884a969fe4da17caryclark } 129555888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (end->t() + next->t()) / 2; 129655888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 129755888e44171ffd48b591d19256884a969fe4da17caryclark break; 129855888e44171ffd48b591d19256884a969fe4da17caryclark } 129955888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT); 130055888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 130155888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 130255888e44171ffd48b591d19256884a969fe4da17caryclark return expanded; 130355888e44171ffd48b591d19256884a969fe4da17caryclark} 130455888e44171ffd48b591d19256884a969fe4da17caryclark 130555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */ 130655888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans 130755888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 130826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* log) const { 130926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 131026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 1311ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1312ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 131326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 131455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* startPtT = coin->coinPtTStart(); 131555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oStartPtT = coin->oppPtTStart(); 131626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(startPtT->contains(oStartPtT)); 131755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 131826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 131926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 132055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 132155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 132230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(oEnd->deleted(), coin); 132330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!start->upCastable(), coin); 132426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 132555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 132655888e44171ffd48b591d19256884a969fe4da17caryclark if (!oTest) { 132755888e44171ffd48b591d19256884a969fe4da17caryclark return; 132855888e44171ffd48b591d19256884a969fe4da17caryclark } 132926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 133055888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->ptT()->contains(oTest->segment()) 133155888e44171ffd48b591d19256884a969fe4da17caryclark || !oTest->ptT()->contains(start->segment())) { 133226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 133355888e44171ffd48b591d19256884a969fe4da17caryclark double startRange = coin->coinPtTEnd()->fT - startPtT->fT; 133430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!startRange, coin); 133526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double startPart = (test->t() - startPtT->fT) / startRange; 133655888e44171ffd48b591d19256884a969fe4da17caryclark double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT; 133730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(!oStartRange, coin); 133826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 133930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark FAIL_IF(startPart == oStartPart, coin); 134055888e44171ffd48b591d19256884a969fe4da17caryclark bool startOver = false; 134155888e44171ffd48b591d19256884a969fe4da17caryclark if (startPart < oStartPart) 134255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddExpandedCoin_Glitch, id, // strange debug formatting lines up with original 134355888e44171ffd48b591d19256884a969fe4da17caryclark oStartPtT->fT + oStartRange * startPart, test); 134455888e44171ffd48b591d19256884a969fe4da17caryclark else log->record(kAddExpandedCoin_Glitch, id, 134555888e44171ffd48b591d19256884a969fe4da17caryclark startPtT->fT + startRange * oStartPart, oTest); 134655888e44171ffd48b591d19256884a969fe4da17caryclark if (false) { 134755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 134855888e44171ffd48b591d19256884a969fe4da17caryclark return; 134926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135055888e44171ffd48b591d19256884a969fe4da17caryclark if (startOver) { 135155888e44171ffd48b591d19256884a969fe4da17caryclark test = start; 135255888e44171ffd48b591d19256884a969fe4da17caryclark oTest = oStart; 135326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135555888e44171ffd48b591d19256884a969fe4da17caryclark if (test != end) { 135630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!test->upCastable()) { 135730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 135830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 135926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 136026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136155888e44171ffd48b591d19256884a969fe4da17caryclark if (oTest != oEnd) { 136255888e44171ffd48b591d19256884a969fe4da17caryclark oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 136355888e44171ffd48b591d19256884a969fe4da17caryclark if (!oTest) { 136455888e44171ffd48b591d19256884a969fe4da17caryclark return; 136555888e44171ffd48b591d19256884a969fe4da17caryclark } 136626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 136955888e44171ffd48b591d19256884a969fe4da17caryclark return; 137055888e44171ffd48b591d19256884a969fe4da17caryclark} 137155888e44171ffd48b591d19256884a969fe4da17caryclark 137255888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addIfMissing() */ 137355888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, 137455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog* log) const { 137555888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fTop); 137655888e44171ffd48b591d19256884a969fe4da17caryclark if (fTop && alreadyAdded(fTop, outer, over1s, over1e)) { // in debug, fTop may be null 137755888e44171ffd48b591d19256884a969fe4da17caryclark return; 137826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 137955888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && alreadyAdded(fHead, outer, over1s, over1e)) { 138055888e44171ffd48b591d19256884a969fe4da17caryclark return; 138155888e44171ffd48b591d19256884a969fe4da17caryclark } 138255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coinPtTEnd(), over1s, over1e); 138355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 138455888e44171ffd48b591d19256884a969fe4da17caryclark return; 138526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 138626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 138755888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */ 138855888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, 138955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd, 139055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 139155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, const char* id, SkPathOpsDebug::GlitchLog* log) const { 139226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 139355888e44171ffd48b591d19256884a969fe4da17caryclark TRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe); 139455888e44171ffd48b591d19256884a969fe4da17caryclark TRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe); 139555888e44171ffd48b591d19256884a969fe4da17caryclark bool swap = coinTs > coinTe; 139655888e44171ffd48b591d19256884a969fe4da17caryclark if (swap) { 139755888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 139826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 139926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { 140026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 140126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140255888e44171ffd48b591d19256884a969fe4da17caryclark if (swap) { 140326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 140426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = coinPtTStart->segment(); 140655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = oppPtTStart->segment(); 140755888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == oppSeg) { 140855888e44171ffd48b591d19256884a969fe4da17caryclark return; 140926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 141030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe); 141155888e44171ffd48b591d19256884a969fe4da17caryclark} 141255888e44171ffd48b591d19256884a969fe4da17caryclark 141355888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */ 141430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 141530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 141630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclarkvoid SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLog* log, 141730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 141830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark double coinTs, double coinTe, double oppTs, double oppTe) const { 141955888e44171ffd48b591d19256884a969fe4da17caryclark SkTDArray<SkCoincidentSpans*> overlaps; 142055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!fTop); // this is (correctly) reversed in addifMissing() 142155888e44171ffd48b591d19256884a969fe4da17caryclark if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) { 142255888e44171ffd48b591d19256884a969fe4da17caryclark return; 142355888e44171ffd48b591d19256884a969fe4da17caryclark } 142455888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 142555888e44171ffd48b591d19256884a969fe4da17caryclark coinTe, oppTs, oppTe, &overlaps)) { 142655888e44171ffd48b591d19256884a969fe4da17caryclark return; 142755888e44171ffd48b591d19256884a969fe4da17caryclark } 142855888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 142955888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 143055888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = overlaps[index]; 143155888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 143255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart()); 143355888e44171ffd48b591d19256884a969fe4da17caryclark } 143455888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 143555888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd()); 143655888e44171ffd48b591d19256884a969fe4da17caryclark } 143755888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 143855888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 143955888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 144055888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart()); 144155888e44171ffd48b591d19256884a969fe4da17caryclark } 144255888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 144355888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 144455888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 144555888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd()); 144655888e44171ffd48b591d19256884a969fe4da17caryclark } 144730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!fHead) { this->debugRelease(id, log, fHead, test); 144830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->debugRelease(id, log, fTop, test); 144955888e44171ffd48b591d19256884a969fe4da17caryclark } 145055888e44171ffd48b591d19256884a969fe4da17caryclark } 145155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 145255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 145330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); 145430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(cs != ce || !cs, coinSeg); 145555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 145655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 145730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); 145855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !cs || !cs->deleted()); 145955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !os || !os->deleted()); 146055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !ce || !ce->deleted()); 146155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !oe || !oe->deleted()); 146255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 146355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 146430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); 146530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csExisting && (csExisting == ce || 146630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); 146730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceExisting && (ceExisting == cs || 146830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); 146955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 147055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 147130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); 147230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osExisting && (osExisting == oe || 147330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); 147430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeExisting && (oeExisting == os || 147530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oeExisting->contains(osExisting ? osExisting : os)), oppSeg); 147655888e44171ffd48b591d19256884a969fe4da17caryclark bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 147755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 147855888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !os) { 147955888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs) 148030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark cs = coinSeg->debugAddT(coinTs, id, log); 148155888e44171ffd48b591d19256884a969fe4da17caryclark if (!os) 148230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark os = oppSeg->debugAddT(oppTs, id, log); 148330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 148430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (cs && os) cs->span()->debugAddOpp(id, log, os->span()); 148555888e44171ffd48b591d19256884a969fe4da17caryclark// cs = csWritable; 148630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// os = osWritable->active(); 148730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg); 148855888e44171ffd48b591d19256884a969fe4da17caryclark } 148955888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce || !oe) { 149055888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce) 149130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark ce = coinSeg->debugAddT(coinTe, id, log); 149255888e44171ffd48b591d19256884a969fe4da17caryclark if (!oe) 149330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark oe = oppSeg->debugAddT(oppTe, id, log); 149430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (ce && oe) ce->span()->debugAddOpp(id, log, oe->span()); 149555888e44171ffd48b591d19256884a969fe4da17caryclark// ce = ceWritable; 149655888e44171ffd48b591d19256884a969fe4da17caryclark// oe = oeWritable; 149755888e44171ffd48b591d19256884a969fe4da17caryclark } 149855888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 149930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(csDeleted, coinSeg); 150030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(osDeleted, oppSeg); 150130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(ceDeleted, coinSeg); 150230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(oeDeleted, oppSeg); 150330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark RETURN_FALSE_IF(!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe), coinSeg); 150455888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = true; 150555888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap) { 150655888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->segment() == coinSeg) { 150755888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 150855888e44171ffd48b591d19256884a969fe4da17caryclark } else { 150955888e44171ffd48b591d19256884a969fe4da17caryclark if (oppTs > oppTe) { 151055888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 151155888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(oppTs, oppTe); 151255888e44171ffd48b591d19256884a969fe4da17caryclark } 151355888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 151455888e44171ffd48b591d19256884a969fe4da17caryclark } 151555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 151655888e44171ffd48b591d19256884a969fe4da17caryclark// if (result) { 151755888e44171ffd48b591d19256884a969fe4da17caryclark// overlap->debugShow(); 151855888e44171ffd48b591d19256884a969fe4da17caryclark// } 151955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 152055888e44171ffd48b591d19256884a969fe4da17caryclark } else { 152155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingCoin_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 152255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 152355888e44171ffd48b591d19256884a969fe4da17caryclark// fHead->debugShow(); 152455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 152555888e44171ffd48b591d19256884a969fe4da17caryclark } 152655888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 152755888e44171ffd48b591d19256884a969fe4da17caryclark return; 152826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 152926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 153055888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing() 153155888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */ 153255888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */ 153355888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again 153426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const { 153526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 153626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 153726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 153826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 153955888e44171ffd48b591d19256884a969fe4da17caryclark // bool added = false; 154055888e44171ffd48b591d19256884a969fe4da17caryclark // fTop = outer; 154155888e44171ffd48b591d19256884a969fe4da17caryclark // fHead = nullptr; 154226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 154326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 154426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 154526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 154655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* outerCoin = outer->coinPtTStart()->segment(); 154755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* outerOpp = outer->oppPtTStart()->segment(); 154855888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin->done() || outerOpp->done()) { 154955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 155055888e44171ffd48b591d19256884a969fe4da17caryclark } 155126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 155255888e44171ffd48b591d19256884a969fe4da17caryclark while ((inner = inner->next())) { 155355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 155426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 155555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* innerCoin = inner->coinPtTStart()->segment(); 155655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* innerOpp = inner->oppPtTStart()->segment(); 155755888e44171ffd48b591d19256884a969fe4da17caryclark if (innerCoin->done() || innerOpp->done()) { 155855888e44171ffd48b591d19256884a969fe4da17caryclark continue; 155955888e44171ffd48b591d19256884a969fe4da17caryclark } 156055888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin == innerCoin) { 156155888e44171ffd48b591d19256884a969fe4da17caryclark if (outerOpp != innerOpp 156255888e44171ffd48b591d19256884a969fe4da17caryclark && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(), 156355888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) { 156455888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(), 156555888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE, 156655888e44171ffd48b591d19256884a969fe4da17caryclark outer->oppPtTStart(), outer->oppPtTEnd(), 156755888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), id, log); 156826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 156955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerCoin == innerOpp) { 157055888e44171ffd48b591d19256884a969fe4da17caryclark if (outerOpp != innerCoin 157155888e44171ffd48b591d19256884a969fe4da17caryclark && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(), 157255888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) { 157355888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(), 157455888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE, 157555888e44171ffd48b591d19256884a969fe4da17caryclark outer->oppPtTStart(), outer->oppPtTEnd(), 157655888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), id, log); 157726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 157855888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerCoin) { 157955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerOpp); 158055888e44171ffd48b591d19256884a969fe4da17caryclark if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), 158155888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) { 158255888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(), 158355888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE, 158455888e44171ffd48b591d19256884a969fe4da17caryclark outer->coinPtTStart(), outer->coinPtTEnd(), 158555888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), id, log); 158626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 158755888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerOpp) { 158855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerCoin); 158955888e44171ffd48b591d19256884a969fe4da17caryclark if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), 159055888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) { 159155888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(), 159255888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE, 159355888e44171ffd48b591d19256884a969fe4da17caryclark outer->coinPtTStart(), outer->coinPtTEnd(), 159455888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), id, log); 159526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 159626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 159755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 159855888e44171ffd48b591d19256884a969fe4da17caryclark } 159955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((outer = outer->next())); 160055888e44171ffd48b591d19256884a969fe4da17caryclark // this->restoreHead(); 160155888e44171ffd48b591d19256884a969fe4da17caryclark return; 160255888e44171ffd48b591d19256884a969fe4da17caryclark} 160355888e44171ffd48b591d19256884a969fe4da17caryclark 160455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release() 160530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclarkvoid SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { 160630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 160730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* prev = nullptr; 160830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* next; 160930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 161030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark next = coin->next(); 161130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (coin == remove) { 161230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (prev) { 161330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// prev->setNext(next); 161430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else if (head == fHead) { 161530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fHead = next; 161630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 161730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// fTop = next; 161830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 161930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark log->record(kReleasedSpan_Glitch, id, coin); 162030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 162130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark prev = coin; 162230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((coin = next)); 162330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 162430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 162530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 162655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 162755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 162855888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 162955888e44171ffd48b591d19256884a969fe4da17caryclark return; 163055888e44171ffd48b591d19256884a969fe4da17caryclark } 163155888e44171ffd48b591d19256884a969fe4da17caryclark do { 163255888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->segment() == deleted 163355888e44171ffd48b591d19256884a969fe4da17caryclark || coin->coinPtTEnd()->segment() == deleted 163455888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTStart()->segment() == deleted 163555888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTEnd()->segment() == deleted) { 163655888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kReleasedSpan_Glitch, id, coin); 163755888e44171ffd48b591d19256884a969fe4da17caryclark } 163855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 163955888e44171ffd48b591d19256884a969fe4da17caryclark} 164055888e44171ffd48b591d19256884a969fe4da17caryclark 164130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 164255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with reorder() 164355888e44171ffd48b591d19256884a969fe4da17caryclark// iterate through all coincident pairs, looking for ranges greater than 1 164455888e44171ffd48b591d19256884a969fe4da17caryclark// if found, see if the opposite pair can match it -- which may require 164555888e44171ffd48b591d19256884a969fe4da17caryclark// reordering the ptT pairs 164655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* log) const { 164755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 164855888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 164955888e44171ffd48b591d19256884a969fe4da17caryclark return; 165055888e44171ffd48b591d19256884a969fe4da17caryclark } 165155888e44171ffd48b591d19256884a969fe4da17caryclark do { 165255888e44171ffd48b591d19256884a969fe4da17caryclark // most commonly, concidence are one span long; check for that first 165355888e44171ffd48b591d19256884a969fe4da17caryclark int intervals = coin->spanCount(); 165430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (intervals <= 0) { 165530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 165630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 165730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (1 == intervals) { 165855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 165955888e44171ffd48b591d19256884a969fe4da17caryclark // SkASSERT(!coin->debugExpand(nullptr, nullptr)); 166055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 166155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 166255888e44171ffd48b591d19256884a969fe4da17caryclark } 166355888e44171ffd48b591d19256884a969fe4da17caryclark coin->debugExpand(id, log); 166455888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->spanCount() <= 0) { 166555888e44171ffd48b591d19256884a969fe4da17caryclark return; 166626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 166755888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if every span in coin has a mate in opp 166855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStart()->span()->upCast(); 166955888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 167055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oppStartBase = coin->oppPtTStart()->span(); 167155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* oppStart = flipped ? oppStartBase->prev() : oppStartBase->upCast(); 167255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("", start, oppStart); 167355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 167455888e44171ffd48b591d19256884a969fe4da17caryclark return; 167526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 167626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 167755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand() 167855888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence 167926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const { 168026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 168126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 168226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 168326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 168526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 168655888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->debugExpand(id, log)) { 168755888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if multiple spans expanded so they are now identical 168855888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = fHead; 168955888e44171ffd48b591d19256884a969fe4da17caryclark do { 169055888e44171ffd48b591d19256884a969fe4da17caryclark if (coin == test) { 169155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 169255888e44171ffd48b591d19256884a969fe4da17caryclark } 169355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == test->coinPtTStart() 169455888e44171ffd48b591d19256884a969fe4da17caryclark && coin->oppPtTStart() == test->oppPtTStart()) { 169555888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, fHead, test->coinPtTStart()); 169655888e44171ffd48b591d19256884a969fe4da17caryclark break; 169755888e44171ffd48b591d19256884a969fe4da17caryclark } 169855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next())); 169955888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 170026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170155888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 170226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 170426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 170555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with removeCollapsed() 170655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRemoveCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log) const { 170726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 170826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 170926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 171026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171155888e44171ffd48b591d19256884a969fe4da17caryclark // SkCoincidentSpans** priorPtr = &fHead; 171226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 171355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == coin->coinPtTEnd()) { 171455888e44171ffd48b591d19256884a969fe4da17caryclark return; 171526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171655888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->oppPtTStart() == coin->oppPtTEnd()) { 171755888e44171ffd48b591d19256884a969fe4da17caryclark return; 171826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171955888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->collapsed(coin->coinPtTEnd())) { 172055888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 172155888e44171ffd48b591d19256884a969fe4da17caryclark// continue; 172226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 172355888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->oppPtTStart()->collapsed(coin->oppPtTEnd())) { 172455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin, coin); 172555888e44171ffd48b591d19256884a969fe4da17caryclark// continue; 172626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 172755888e44171ffd48b591d19256884a969fe4da17caryclark // priorPtr = &coin->nextPtr(); 172855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 172955888e44171ffd48b591d19256884a969fe4da17caryclark return; 173026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 173126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 173255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark() 173355888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 173426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const { 173526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 173626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 173726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 173826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 173926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 174030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!coin->coinPtTStartWritable()->span()->upCastable()) { 174130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 174230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 174355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 174455888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(start->deleted()); 174555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 174655888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(end->deleted()); 174755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 174855888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oStart->deleted()); 174955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 175055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oEnd->deleted()); 175155888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 175226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 175326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 175426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 175555888e44171ffd48b591d19256884a969fe4da17caryclark /* coin and opp spans may not match up. Mark the ends, and then let the interior 175655888e44171ffd48b591d19256884a969fe4da17caryclark get marked as many times as the spans allow */ 175755888e44171ffd48b591d19256884a969fe4da17caryclark start->debugInsertCoincidence(id, log, oStart->upCast()); 175855888e44171ffd48b591d19256884a969fe4da17caryclark end->debugInsertCoinEnd(id, log, oEnd); 175955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = start->segment(); 176055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oSegment = oStart->segment(); 176126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 176226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 176355888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->upCast()->next()) != end) { 176430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!next->upCastable()) { 176530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 176630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 176755888e44171ffd48b591d19256884a969fe4da17caryclark if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flipped), false) { 176855888e44171ffd48b591d19256884a969fe4da17caryclark return; 176926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 177055888e44171ffd48b591d19256884a969fe4da17caryclark } 177155888e44171ffd48b591d19256884a969fe4da17caryclark while ((oNext = oNext->upCast()->next()) != oEnd) { 177230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!oNext->upCastable()) { 177330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark return; 177430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 177555888e44171ffd48b591d19256884a969fe4da17caryclark if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flipped), false) { 177655888e44171ffd48b591d19256884a969fe4da17caryclark return; 177726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 177855888e44171ffd48b591d19256884a969fe4da17caryclark } 177955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 178055888e44171ffd48b591d19256884a969fe4da17caryclark return; 178155888e44171ffd48b591d19256884a969fe4da17caryclark} 178255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 178355888e44171ffd48b591d19256884a969fe4da17caryclark 178455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 178555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 178655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 178730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkCoincidentSpans* head = coin; 178855888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 178955888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->collapsed(test)) { 179055888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 179155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 179226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 179355888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 179455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 179555888e44171ffd48b591d19256884a969fe4da17caryclark } 179630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->debugRelease(id, log, head, coin); 179755888e44171ffd48b591d19256884a969fe4da17caryclark } 179855888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 179955888e44171ffd48b591d19256884a969fe4da17caryclark } 180055888e44171ffd48b591d19256884a969fe4da17caryclark} 180155888e44171ffd48b591d19256884a969fe4da17caryclark 180255888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 180355888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 180455888e44171ffd48b591d19256884a969fe4da17caryclark this->debugMarkCollapsed(id, log, fHead, test); 180555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugMarkCollapsed(id, log, fTop, test); 180626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 180726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 180826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 180955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const { 181055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 181155888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->segment()->debugID(), 181255888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->fT, coinPtTEnd()->fT); 181355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 181455888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->segment()->debugID(), 181555888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->fT, oppPtTEnd()->fT); 181655888e44171ffd48b591d19256884a969fe4da17caryclark} 181755888e44171ffd48b591d19256884a969fe4da17caryclark 1818624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 181955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 182055888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* span = fHead; 1821624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 182255888e44171ffd48b591d19256884a969fe4da17caryclark span->debugShow(); 182355888e44171ffd48b591d19256884a969fe4da17caryclark span = span->next(); 1824624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 182555888e44171ffd48b591d19256884a969fe4da17caryclark#endif 1826624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 1827624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 182826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 182955888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end, 183055888e44171ffd48b591d19256884a969fe4da17caryclark double oStart, double oEnd, const SkOpSegment* oSegment, 183155888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 183255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(next != end); 183355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!next->contains(end) || log); 183455888e44171ffd48b591d19256884a969fe4da17caryclark if (next->t() > end->t()) { 183555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(next, end); 183655888e44171ffd48b591d19256884a969fe4da17caryclark } 183755888e44171ffd48b591d19256884a969fe4da17caryclark do { 183855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = next->ptT(); 183955888e44171ffd48b591d19256884a969fe4da17caryclark int index = 0; 184055888e44171ffd48b591d19256884a969fe4da17caryclark bool somethingBetween; 184155888e44171ffd48b591d19256884a969fe4da17caryclark do { 184255888e44171ffd48b591d19256884a969fe4da17caryclark ++index; 184355888e44171ffd48b591d19256884a969fe4da17caryclark ptT = ptT->next(); 184455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* checkPtT = next->ptT(); 184555888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT == checkPtT) { 184655888e44171ffd48b591d19256884a969fe4da17caryclark break; 184755888e44171ffd48b591d19256884a969fe4da17caryclark } 184855888e44171ffd48b591d19256884a969fe4da17caryclark bool looped = false; 184955888e44171ffd48b591d19256884a969fe4da17caryclark for (int check = 0; check < index; ++check) { 185055888e44171ffd48b591d19256884a969fe4da17caryclark if ((looped = checkPtT == ptT)) { 185155888e44171ffd48b591d19256884a969fe4da17caryclark break; 185255888e44171ffd48b591d19256884a969fe4da17caryclark } 185355888e44171ffd48b591d19256884a969fe4da17caryclark checkPtT = checkPtT->next(); 185455888e44171ffd48b591d19256884a969fe4da17caryclark } 185555888e44171ffd48b591d19256884a969fe4da17caryclark if (looped) { 185655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 185755888e44171ffd48b591d19256884a969fe4da17caryclark break; 185855888e44171ffd48b591d19256884a969fe4da17caryclark } 185955888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->deleted()) { 186055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 186155888e44171ffd48b591d19256884a969fe4da17caryclark } 186255888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() != oSegment) { 186355888e44171ffd48b591d19256884a969fe4da17caryclark continue; 186455888e44171ffd48b591d19256884a969fe4da17caryclark } 186555888e44171ffd48b591d19256884a969fe4da17caryclark somethingBetween |= between(oStart, ptT->fT, oEnd); 186655888e44171ffd48b591d19256884a969fe4da17caryclark } while (true); 186755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(somethingBetween); 186855888e44171ffd48b591d19256884a969fe4da17caryclark } while (next != end && (next = next->upCast()->next())); 186955888e44171ffd48b591d19256884a969fe4da17caryclark} 187055888e44171ffd48b591d19256884a969fe4da17caryclark 187155888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 187255888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 187355888e44171ffd48b591d19256884a969fe4da17caryclark if (!list) { 187455888e44171ffd48b591d19256884a969fe4da17caryclark return; 187555888e44171ffd48b591d19256884a969fe4da17caryclark } 187655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 187755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 187855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 187955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 188055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg != test->oppPtTStart()->segment()); 188155888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 188255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tcs, 1)); 188355888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 188455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tce, 1)); 188555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tcs < tce); 188655888e44171ffd48b591d19256884a969fe4da17caryclark double tos = test->oppPtTStart()->fT; 188755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tos, 1)); 188855888e44171ffd48b591d19256884a969fe4da17caryclark double toe = test->oppPtTEnd()->fT; 188955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, toe, 1)); 189055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tos != toe); 189155888e44171ffd48b591d19256884a969fe4da17caryclark if (tos > toe) { 189255888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(tos, toe); 189355888e44171ffd48b591d19256884a969fe4da17caryclark } 189455888e44171ffd48b591d19256884a969fe4da17caryclark do { 189555888e44171ffd48b591d19256884a969fe4da17caryclark double lcs, lce, los, loe; 189655888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == list->coinPtTStart()->segment()) { 189755888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->oppPtTStart()->segment()) { 189855888e44171ffd48b591d19256884a969fe4da17caryclark continue; 189955888e44171ffd48b591d19256884a969fe4da17caryclark } 190055888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->coinPtTStart()->fT; 190155888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->coinPtTEnd()->fT; 190255888e44171ffd48b591d19256884a969fe4da17caryclark los = list->oppPtTStart()->fT; 190355888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->oppPtTEnd()->fT; 190455888e44171ffd48b591d19256884a969fe4da17caryclark if (los > loe) { 190555888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(los, loe); 190655888e44171ffd48b591d19256884a969fe4da17caryclark } 190755888e44171ffd48b591d19256884a969fe4da17caryclark } else if (coinSeg == list->oppPtTStart()->segment()) { 190855888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->coinPtTStart()->segment()) { 190955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 191055888e44171ffd48b591d19256884a969fe4da17caryclark } 191155888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->oppPtTStart()->fT; 191255888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->oppPtTEnd()->fT; 191355888e44171ffd48b591d19256884a969fe4da17caryclark if (lcs > lce) { 191455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(lcs, lce); 191555888e44171ffd48b591d19256884a969fe4da17caryclark } 191655888e44171ffd48b591d19256884a969fe4da17caryclark los = list->coinPtTStart()->fT; 191755888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->coinPtTEnd()->fT; 191855888e44171ffd48b591d19256884a969fe4da17caryclark } else { 191955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 192055888e44171ffd48b591d19256884a969fe4da17caryclark } 192155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tce < lcs || lce < tcs); 192255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(toe < los || loe < tos); 192355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((list = list->next())); 192455888e44171ffd48b591d19256884a969fe4da17caryclark} 192555888e44171ffd48b591d19256884a969fe4da17caryclark 192655888e44171ffd48b591d19256884a969fe4da17caryclark 192755888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 192855888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 192955888e44171ffd48b591d19256884a969fe4da17caryclark // check for overlapping coincident spans 193055888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = head; 193155888e44171ffd48b591d19256884a969fe4da17caryclark while (test) { 193255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* next = test->next(); 193355888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlap(test, next, id, log); 193455888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlap(test, opt, id, log); 193555888e44171ffd48b591d19256884a969fe4da17caryclark test = next; 193655888e44171ffd48b591d19256884a969fe4da17caryclark } 193755888e44171ffd48b591d19256884a969fe4da17caryclark} 193855888e44171ffd48b591d19256884a969fe4da17caryclark 193955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 194055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLog* log) const { 194155888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(fHead, fTop, id, log); 194255888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(fTop, nullptr, id, log); 194355888e44171ffd48b591d19256884a969fe4da17caryclark} 194455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 194555888e44171ffd48b591d19256884a969fe4da17caryclark 194655888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 194755888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 194855888e44171ffd48b591d19256884a969fe4da17caryclark // look for pts inside coincident spans that are not inside the opposite spans 194955888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = head; 195055888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 195155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 195255888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->segment())); 195355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 195455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 195555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 195655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 195755888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 195855888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 195955888e44171ffd48b591d19256884a969fe4da17caryclark id, log); 196055888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 196155888e44171ffd48b591d19256884a969fe4da17caryclark coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 196255888e44171ffd48b591d19256884a969fe4da17caryclark id, log); 196355888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 196455888e44171ffd48b591d19256884a969fe4da17caryclark } 196555888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(head, opt, id, log); 196655888e44171ffd48b591d19256884a969fe4da17caryclark} 196755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 196855888e44171ffd48b591d19256884a969fe4da17caryclark 196955888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugValidate() const { 197055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 197155888e44171ffd48b591d19256884a969fe4da17caryclark // if (fGlobalState->debugCheckHealth()) { 197255888e44171ffd48b591d19256884a969fe4da17caryclark// return; 197355888e44171ffd48b591d19256884a969fe4da17caryclark// } 197455888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fHead, fTop, nullptr, nullptr); 197555888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fTop, nullptr, nullptr, nullptr); 197655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 197755888e44171ffd48b591d19256884a969fe4da17caryclark} 197855888e44171ffd48b591d19256884a969fe4da17caryclark 197955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 198055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const { 198155888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fHead, fTop, id, log); 198255888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fTop, nullptr, id, log); 198355888e44171ffd48b591d19256884a969fe4da17caryclark} 198455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 198555888e44171ffd48b591d19256884a969fe4da17caryclark 198655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 198726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* log) const { 198826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 198926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 199026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark segment->debugCheckHealth(id, log); 199126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((segment = segment->next())); 199226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 199326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 199455888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence() 199555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 199655888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fCount > 0); 199726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 199855888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 199926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 200055888e44171ffd48b591d19256884a969fe4da17caryclark if (fState->angleCoincidence()) { 200155888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ANGLE 200255888e44171ffd48b591d19256884a969fe4da17caryclark// segment->debugCheckAngleCoin(); 200355888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 200455888e44171ffd48b591d19256884a969fe4da17caryclark } else if (segment->debugMissingCoincidence(id, log), false) { 200555888e44171ffd48b591d19256884a969fe4da17caryclark// result = true; 200655888e44171ffd48b591d19256884a969fe4da17caryclark// see FIXME in missingCoincidence() 200755888e44171ffd48b591d19256884a969fe4da17caryclark// 200855888e44171ffd48b591d19256884a969fe4da17caryclark// 200955888e44171ffd48b591d19256884a969fe4da17caryclark// 201055888e44171ffd48b591d19256884a969fe4da17caryclark // continue; 201155888e44171ffd48b591d19256884a969fe4da17caryclark } 201255888e44171ffd48b591d19256884a969fe4da17caryclark segment = segment->next(); 201355888e44171ffd48b591d19256884a969fe4da17caryclark } while (segment); 201455888e44171ffd48b591d19256884a969fe4da17caryclark return; 201526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 201626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 201726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2018025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2019025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSegment::debugResetCoinT() const { 2020025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseIndex = -1; 2021025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMin = 1; 2022025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugBaseMax = -1; 2023025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastIndex = -1; 2024025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMin = 1; 2025025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark fDebugLastMax = -1; 2026025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2027025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2028025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 20294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 2030025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2031025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark { 2032025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpSpanBase* span = &fHead; 2033025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2034025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugResetCoinT(); 2035025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2036025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span = &fHead; 2037025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark int index = 0; 2038025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2039025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark span->debugSetCoinT(index++); 2040025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (!span->final() && (span = span->upCast()->next())); 2041025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2042025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 204355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 204455888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 204555888e44171ffd48b591d19256884a969fe4da17caryclark return; 204655888e44171ffd48b591d19256884a969fe4da17caryclark } 204755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 20484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 204954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 205054359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 205196fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 205254359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 20534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 205454359294a7c9dc54802d512a5d891a35c1663392caryclark do { 205554359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 205654359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 205754359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 205854359294a7c9dc54802d512a5d891a35c1663392caryclark } 205954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 206054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 206154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 206254359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 206354359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 206454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 206554359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 206654359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 206754359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 206854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 206954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 207008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 207154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 207254359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 207354359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 207454359294a7c9dc54802d512a5d891a35c1663392caryclark} 207554359294a7c9dc54802d512a5d891a35c1663392caryclark 207655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 207730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 207830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with addOpp() 207930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclarkvoid SkOpSpanBase::debugAddOpp(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 208030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 208130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!oppPrev) { 208255888e44171ffd48b591d19256884a969fe4da17caryclark return; 208326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 208430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->debugMergeMatches(id, log, opp); 208530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->ptT()->debugAddOpp(opp->ptT(), oppPrev); 208630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->debugCheckForCollapsedCoincidence(id, log); 208726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 208826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 208955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 209055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 209155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coins = this->globalState()->coincidence(); 209255888e44171ffd48b591d19256884a969fe4da17caryclark if (coins->isEmpty()) { 209355888e44171ffd48b591d19256884a969fe4da17caryclark return; 209455888e44171ffd48b591d19256884a969fe4da17caryclark } 209555888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span 209655888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop 209755888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span 209855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 209955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* test = head; 210026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 210155888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->coincident()) { 210255888e44171ffd48b591d19256884a969fe4da17caryclark continue; 210326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 210455888e44171ffd48b591d19256884a969fe4da17caryclark coins->debugMarkCollapsed(id, log, test); 210555888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next()) != head); 210626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 210755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 210826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 210954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 211054359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 211154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 211254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 211354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 211454359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 211554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 211654359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 211754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 211854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 211954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 212054359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 212154359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 212254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 212354359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 212454359294a7c9dc54802d512a5d891a35c1663392caryclark } 212554359294a7c9dc54802d512a5d891a35c1663392caryclark } 212654359294a7c9dc54802d512a5d891a35c1663392caryclark } 212754359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 212854359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 212954359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 213054359294a7c9dc54802d512a5d891a35c1663392caryclark} 213154359294a7c9dc54802d512a5d891a35c1663392caryclark 213255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 213355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd() 213455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugInsertCoinEnd(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 213555888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoinEnd(coin)) { 213655888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoinEnd(this)); 213755888e44171ffd48b591d19256884a969fe4da17caryclark return; 213855888e44171ffd48b591d19256884a969fe4da17caryclark } 213955888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 214055888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 214155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinEnd_Glitch, id, this, coin); 214255888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoinEnd = this->fCoinEnd; 214355888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoinEnd = coinNext; 214455888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 214555888e44171ffd48b591d19256884a969fe4da17caryclark} 214655888e44171ffd48b591d19256884a969fe4da17caryclark 214755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mergeContained() 214855888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog* log, const SkPathOpsBounds& bounds, bool* deleted) const { 214955888e44171ffd48b591d19256884a969fe4da17caryclark // while adjacent spans' points are contained by the bounds, merge them 215055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* prev = this; 215155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* seg = this->segment(); 215255888e44171ffd48b591d19256884a969fe4da17caryclark while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisjoint(prev, this)) { 215355888e44171ffd48b591d19256884a969fe4da17caryclark if (prev->prev()) { 215455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, this, prev); 215555888e44171ffd48b591d19256884a969fe4da17caryclark } else if (this->final()) { 215655888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, this, prev); 215755888e44171ffd48b591d19256884a969fe4da17caryclark // return; 215855888e44171ffd48b591d19256884a969fe4da17caryclark } else { 215955888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, prev, this); 216026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 216126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 216255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* current = this; 216355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* next = this; 216455888e44171ffd48b591d19256884a969fe4da17caryclark while (next->upCastable() && (next = next->upCast()->next()) 216555888e44171ffd48b591d19256884a969fe4da17caryclark && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) { 216655888e44171ffd48b591d19256884a969fe4da17caryclark if (!current->prev() && next->final()) { 216755888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 216855888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 216955888e44171ffd48b591d19256884a969fe4da17caryclark } 217055888e44171ffd48b591d19256884a969fe4da17caryclark if (current->prev()) { 217155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 217255888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 217355888e44171ffd48b591d19256884a969fe4da17caryclark } else { 217455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 217555888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 217655888e44171ffd48b591d19256884a969fe4da17caryclark } 217755888e44171ffd48b591d19256884a969fe4da17caryclark } 217855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 217955888e44171ffd48b591d19256884a969fe4da17caryclark // this->globalState()->coincidence()->debugValidate(); 218055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 218126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 218230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 218330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Commented-out lines keep this in sync with mergeMatches() 218430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// Look to see if pt-t linked list contains same segment more than once 218530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if so, and if each pt-t is directly pointed to by spans in that segment, 218630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// merge them 218730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// keep the points, but remove spans so that the segment doesn't have 2 or more 218830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// spans pointing to the same pt-t loop at different loop elements 218930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclarkvoid SkOpSpanBase::debugMergeMatches(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 219030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* test = &fPtT; 219130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* testNext; 219230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* stop = test; 219330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 219430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark testNext = test->next(); 219530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (test->deleted()) { 219630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 219730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 219830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* testBase = test->span(); 219930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(testBase->ptT() == test); 220030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSegment* segment = test->segment(); 220130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (segment->done()) { 220230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 220330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 220430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* inner = opp->ptT(); 220530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* innerStop = inner; 220630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark do { 220730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->segment() != segment) { 220830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 220930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 221030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (inner->deleted()) { 221130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 221230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 221330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpSpanBase* innerBase = inner->span(); 221430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(innerBase->ptT() == inner); 221530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // when the intersection is first detected, the span base is marked if there are 221630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark // more than one point in the intersection. 221730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) { 221830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(inner->fT)) { 221930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark log->record(kMergeMatches_Glitch, id, innerBase, test); 222030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 222130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkASSERT(inner->fT != test->fT); 222230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (!zero_or_one(test->fT)) { 222330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark log->record(kMergeMatches_Glitch, id, testBase, inner); 222430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } else { 222530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark log->record(kMergeMatches_Glitch, id, segment); 222630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(testBase->debugSetDeleted()); 222730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// test->setDeleted(); 222830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// SkDEBUGCODE(innerBase->debugSetDeleted()); 222930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// inner->setDeleted(); 223030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 223130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 223230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#ifdef SK_DEBUG // assert if another undeleted entry points to segment 223330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark const SkOpPtT* debugInner = inner; 223430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark while ((debugInner = debugInner->next()) != innerStop) { 223530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->segment() != segment) { 223630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 223730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 223830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark if (debugInner->deleted()) { 223930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark continue; 224030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 224130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark SkOPASSERT(0); 224230b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } 224330b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark#endif 224430b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 224530b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark// } 224630b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark break; 224730b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((inner = inner->next()) != innerStop); 224830b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark } while ((test = testNext) != stop); 224930b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark this->debugCheckForCollapsedCoincidence(id, log); 225030b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark} 225130b9fdd6a1d607bde20c793af65b5e2e8a1737cacaryclark 225255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 225326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 2254025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugResetCoinT() const { 2255025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2256025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2257025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2258025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugResetCoinT(); 2259025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2260025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2261025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2262025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2263025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2264025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpSpanBase::debugSetCoinT(int index) const { 2265025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2266025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark const SkOpPtT* ptT = &fPtT; 2267025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark do { 2268025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark if (!ptT->deleted()) { 2269025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT->debugSetCoinT(index); 2270025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } 2271025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark ptT = ptT->next(); 2272025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark } while (ptT != &fPtT); 2273025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2274025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2275025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 227626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 227726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 227826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 227926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 228026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 228126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 228226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 228326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 228426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 228526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 228626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 228726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 228826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 228954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 229055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 229155888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 229255888e44171ffd48b591d19256884a969fe4da17caryclark return; 229355888e44171ffd48b591d19256884a969fe4da17caryclark } 229455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 229554359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 229654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 229754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 229854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 229954359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 230054359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 230154359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 230254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 230354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 230454359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 230554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 230654359294a7c9dc54802d512a5d891a35c1663392caryclark } 230754359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 230854359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 230954359294a7c9dc54802d512a5d891a35c1663392caryclark } 231054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 231154359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 231254359294a7c9dc54802d512a5d891a35c1663392caryclark } 23134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 231454359294a7c9dc54802d512a5d891a35c1663392caryclark} 231554359294a7c9dc54802d512a5d891a35c1663392caryclark 231654359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 231754359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 231854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 231954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 232054359294a7c9dc54802d512a5d891a35c1663392caryclark do { 232154359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 232254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 232354359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 232454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 232554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 232654359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 232754359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 232854359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 232954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 233054359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 233154359294a7c9dc54802d512a5d891a35c1663392caryclark } 233254359294a7c9dc54802d512a5d891a35c1663392caryclark } 233354359294a7c9dc54802d512a5d891a35c1663392caryclark } 233454359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 233554359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 233654359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 233754359294a7c9dc54802d512a5d891a35c1663392caryclark} 233854359294a7c9dc54802d512a5d891a35c1663392caryclark 233955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 234055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header 234155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 234255888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoincidence(coin)) { 234355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoincidence(this)); 234455888e44171ffd48b591d19256884a969fe4da17caryclark return; 234555888e44171ffd48b591d19256884a969fe4da17caryclark } 234655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 234755888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 234855888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinStart_Glitch, id, this, coin); 234955888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoincident = this->fCoincident; 235055888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoincident = coinNext; 235155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 235255888e44171ffd48b591d19256884a969fe4da17caryclark} 235355888e44171ffd48b591d19256884a969fe4da17caryclark 235455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() 235555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped) const { 235655888e44171ffd48b591d19256884a969fe4da17caryclark if (this->containsCoincidence(segment)) { 235755888e44171ffd48b591d19256884a969fe4da17caryclark return; 235855888e44171ffd48b591d19256884a969fe4da17caryclark } 235955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* next = &fPtT; 236055888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->next()) != &fPtT) { 236155888e44171ffd48b591d19256884a969fe4da17caryclark if (next->segment() == segment) { 236255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinInsert_Glitch, id, flipped ? next->span()->prev() : next->span()); 236355888e44171ffd48b591d19256884a969fe4da17caryclark return; 236455888e44171ffd48b591d19256884a969fe4da17caryclark } 236555888e44171ffd48b591d19256884a969fe4da17caryclark } 236655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 236755888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinMissing_Glitch, id, segment, this); 236855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 236955888e44171ffd48b591d19256884a969fe4da17caryclark} 237055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 237155888e44171ffd48b591d19256884a969fe4da17caryclark 2372624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 2373624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 2374624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 2375624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 2376624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 2377624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2378624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 2379624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 2380624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 2381624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 2382624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 2383624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2384624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 2385624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 2386624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 2387624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2388624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 2389624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2390624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 2391624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 2392624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2393624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 239454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 239554359294a7c9dc54802d512a5d891a35c1663392caryclark 239655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp() 239729b2563afb1677515739f1d24fb27733626eca92caryclarkvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { 239829b2563afb1677515739f1d24fb27733626eca92caryclark SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); 239955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(this != opp); 240055888e44171ffd48b591d19256884a969fe4da17caryclark// this->fNext = opp; 240129b2563afb1677515739f1d24fb27733626eca92caryclark SkASSERT(oppPrev != oldNext); 240255888e44171ffd48b591d19256884a969fe4da17caryclark// oppPrev->fNext = oldNext; 240355888e44171ffd48b591d19256884a969fe4da17caryclark} 240455888e44171ffd48b591d19256884a969fe4da17caryclark 240526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 240626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 240726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 240826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 240926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 241026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 241126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 241226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 241326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 241426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 241526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 241626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 241726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 241826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 241926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 242026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 242126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 242226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 242326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 242426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 242526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 242626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 242726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 242826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 242926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 243026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 243126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 243226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 243326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 243426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 243526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 243626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 243726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 243826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 243926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 244026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 244126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 244226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 244326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 244426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 244554359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 244654359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 244754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 244854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 244954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 245054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 245154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 245254359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 245354359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 245454359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 245554359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 245654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 245754359294a7c9dc54802d512a5d891a35c1663392caryclark } 245854359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 245954359294a7c9dc54802d512a5d891a35c1663392caryclark } 24604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 246226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 246326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 246426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 246526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 246626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 246726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 246826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 246954359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 247054359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 247154359294a7c9dc54802d512a5d891a35c1663392caryclark} 247254359294a7c9dc54802d512a5d891a35c1663392caryclark 247329b2563afb1677515739f1d24fb27733626eca92caryclarkconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { 247429b2563afb1677515739f1d24fb27733626eca92caryclark return this->oppPrev(const_cast<SkOpPtT*>(opp)); 247529b2563afb1677515739f1d24fb27733626eca92caryclark} 247629b2563afb1677515739f1d24fb27733626eca92caryclark 2477025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugResetCoinT() const { 2478025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2479025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugResetCoinT(); 2480025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2481025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2482025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 2483025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclarkvoid SkOpPtT::debugSetCoinT(int index) const { 2484025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#if DEBUG_COINCIDENCE_ORDER 2485025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark this->segment()->debugSetCoinT(index, fT); 2486025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark#endif 2487025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark} 2488025b11ecde8733d9b3eee54e132cc50a5ce8eb78caryclark 248954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 249055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 249155888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 249255888e44171ffd48b591d19256884a969fe4da17caryclark return; 249355888e44171ffd48b591d19256884a969fe4da17caryclark } 249455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 249554359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 24964e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark SkOpGlobalState::Phase phase = contour()->globalState()->phase(); 24974e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark if (phase == SkOpGlobalState::kIntersecting 24984e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark || phase == SkOpGlobalState::kFixWinding) { 249954359294a7c9dc54802d512a5d891a35c1663392caryclark return; 25004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 250154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 250254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 250354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 250454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 25054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 25064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 25071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 25081049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 25091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 25101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 25111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 25121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 25131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 25141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 25151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 25161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 25171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 25181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 25201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 25211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 25231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 25241049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 25251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 25261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 25271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 25281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 25291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 25301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 25311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 25341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 25351049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 25361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 25371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 25381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 25391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 25401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 25411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 25421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 25431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 25441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 25451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 25461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 25471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 25481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 25491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 25501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 25511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 25521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 25531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 25541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 25551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 25561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 25571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 25581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 25591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 25601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 25611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 25621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 25631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 25641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 25651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 25661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 25671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 25681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 25691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 25701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 25711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 25741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 25751049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 25761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 25771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 25781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 25791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 25801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 25811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 25821049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 25831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 25841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 25851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 258696fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 25871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 25881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 25891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 25901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 25911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 25921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 25931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 25941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 25951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 25961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 25971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 25981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 25991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 26001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 26011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 26021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 26031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 26041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 26051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 26061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 26071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 26081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 26091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 26101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 2611