SkPathOpsDebug.cpp revision d6562000efca50bc2bfddae8dcb69dce6b8c0950
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 1555888e44171ffd48b591d19256884a969fe4da17caryclarkclass SkCoincidentSpans; 1626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 1854359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail; 1954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 21624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 22624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 23624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 24624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 25624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 26624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 27624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 28624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 29624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 32570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 34fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 35fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 36570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 3754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 3854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 4054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 4826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 4955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 5026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkenum GlitchType { 5126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddCorruptCoin_Glitch, 5226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddExpandedCoin_Glitch, 5355888e44171ffd48b591d19256884a969fe4da17caryclark kAddExpandedFail_Glitch, 5455888e44171ffd48b591d19256884a969fe4da17caryclark kAddIfMissingCoin_Glitch, 5526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddMissingCoin_Glitch, 5655888e44171ffd48b591d19256884a969fe4da17caryclark kAddMissingExtend_Glitch, 5755888e44171ffd48b591d19256884a969fe4da17caryclark kAddOrOverlap_Glitch, 5826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedCoin_Glitch, 5926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedDone_Glitch, 6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedOppValue_Glitch, 6126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedSpan_Glitch, 6226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedWindValue_Glitch, 6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kDeletedCoin_Glitch, 6426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kExpandCoin_Glitch, 6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinEnd_Glitch, 6626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinInsert_Glitch, 6755888e44171ffd48b591d19256884a969fe4da17caryclark kMarkCoinMissing_Glitch, 6855888e44171ffd48b591d19256884a969fe4da17caryclark kMarkCoinStart_Glitch, 6955888e44171ffd48b591d19256884a969fe4da17caryclark kMergeContained_Glitch, 7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingCoin_Glitch, 7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingDone_Glitch, 7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingIntersection_Glitch, 7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMoveMultiple_Glitch, 7455888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyClearAll_Glitch, 7555888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyClearAll2_Glitch, 7655888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyMerge_Glitch, 7755888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyMergeFinal_Glitch, 7855888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyRelease_Glitch, 7955888e44171ffd48b591d19256884a969fe4da17caryclark kMoveNearbyReleaseFinal_Glitch, 8055888e44171ffd48b591d19256884a969fe4da17caryclark kReleasedSpan_Glitch, 8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnaligned_Glitch, 8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedHead_Glitch, 8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedTail_Glitch, 8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 8655888e44171ffd48b591d19256884a969fe4da17caryclarkstatic const int kGlitchType_Count = kUnalignedTail_Glitch + 1; 8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 8826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 8926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* fStage; 9026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 9226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 9355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* fOppSegment; 9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 9855888e44171ffd48b591d19256884a969fe4da17caryclark double fStartT; 9955888e44171ffd48b591d19256884a969fe4da17caryclark double fEndT; 10055888e44171ffd48b591d19256884a969fe4da17caryclark double fOppStartT; 10155888e44171ffd48b591d19256884a969fe4da17caryclark double fOppEndT; 10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchType fType; 10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* recordCommon(GlitchType type, const char* stage) { 10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fStage = stage; 11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 11226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 11355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = nullptr; 11426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 11855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = SK_ScalarNaN; 11955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = SK_ScalarNaN; 12055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = SK_ScalarNaN; 12155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = SK_ScalarNaN; 12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 12826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 12926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 13026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 13126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 13226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 13326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 13455888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 13555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 13655888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 13755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 13855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = ptT; 13955888e44171ffd48b591d19256884a969fe4da17caryclark } 14055888e44171ffd48b591d19256884a969fe4da17caryclark 14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 14255888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* opp = NULL) { 14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 14455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 14555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 14655888e44171ffd48b591d19256884a969fe4da17caryclark if (opp) { 14755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = opp->coinPtTStart(); 14855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = opp->coinPtTEnd(); 14955888e44171ffd48b591d19256884a969fe4da17caryclark } 15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 15526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 15755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 15926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, double t, 16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 16555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 16626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 16926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 17026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 17255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 17355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 17426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 17555888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSpan = coinSpan; 17655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndSpan = endSpan; 17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 18055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* base) { 18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 18255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = base; 18355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 18455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = coin->coinPtTEnd(); 18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 19126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 19326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 19426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 19526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 19655888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg, double startT, 19755888e44171ffd48b591d19256884a969fe4da17caryclark double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 19855888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 19955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 20055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = startT; 20155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndT = endT; 20255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppSegment = oppSeg; 20355888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppStartT = oppStartT; 20455888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fOppEndT = oppEndT; 20555888e44171ffd48b591d19256884a969fe4da17caryclark } 20655888e44171ffd48b591d19256884a969fe4da17caryclark 20755888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg, 20855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span) { 20955888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 21055888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 21155888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 21255888e44171ffd48b591d19256884a969fe4da17caryclark } 21355888e44171ffd48b591d19256884a969fe4da17caryclark 21455888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, double t, const SkOpSpanBase* span) { 21555888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 21655888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fStartT = t; 21755888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fBase = span; 21855888e44171ffd48b591d19256884a969fe4da17caryclark } 21955888e44171ffd48b591d19256884a969fe4da17caryclark 22055888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkOpSegment* seg) { 22155888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 22255888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fSegment = seg; 22355888e44171ffd48b591d19256884a969fe4da17caryclark } 22455888e44171ffd48b591d19256884a969fe4da17caryclark 22555888e44171ffd48b591d19256884a969fe4da17caryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 22655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT) { 22755888e44171ffd48b591d19256884a969fe4da17caryclark SpanGlitch* glitch = recordCommon(type, stage); 22855888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fCoinSpan = coin->coinPtTStart(); 22955888e44171ffd48b591d19256884a969fe4da17caryclark glitch->fEndSpan = ptT; 23055888e44171ffd48b591d19256884a969fe4da17caryclark } 23155888e44171ffd48b591d19256884a969fe4da17caryclark 23226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 23326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 23455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 23526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 23655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 23755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 23855888e44171ffd48b591d19256884a969fe4da17caryclark SkOpContour* contour = contourList; 23955888e44171ffd48b591d19256884a969fe4da17caryclark do { 24055888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugShowActiveSpans(); 24155888e44171ffd48b591d19256884a969fe4da17caryclark } while ((contour = contour->next())); 24255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 24355888e44171ffd48b591d19256884a969fe4da17caryclark} 24455888e44171ffd48b591d19256884a969fe4da17caryclark 24555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 24626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { 24755888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(true); 24855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 24926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 25026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 25126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 25255888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugCheckValid(id, &glitches); // don't call validate; spans may be inconsistent 25326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 25426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark contour->debugCheckHealth(id, &glitches); 25555888e44171ffd48b591d19256884a969fe4da17caryclark contour->debugMissingCoincidence(id, &glitches); 25626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 25755888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugRemoveCollapsed(id, &glitches); 25826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddMissing(id, &glitches); 25926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugExpand(id, &glitches); 26026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddExpanded(id, &glitches); 26126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugMark(id, &glitches); 26255888e44171ffd48b591d19256884a969fe4da17caryclark coincidence->debugReorder(id, &glitches); 26326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 26426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 26526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 26626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 26726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 26826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 26926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 27026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 27126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(" %s\n", id); 27255888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 27355888e44171ffd48b591d19256884a969fe4da17caryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 27455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%02d: ", index); 27555888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fBase) { 27655888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" base=%d", glitch.fBase->debugID()); 27755888e44171ffd48b591d19256884a969fe4da17caryclark } 27855888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSuspect) { 27955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" base=%d", glitch.fSuspect->debugID()); 28055888e44171ffd48b591d19256884a969fe4da17caryclark } 28155888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fSegment) { 28255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fSegment->debugID()); 28355888e44171ffd48b591d19256884a969fe4da17caryclark } 28455888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fCoinSpan) { 28555888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" coinSpan=%d", glitch.fCoinSpan->debugID()); 28655888e44171ffd48b591d19256884a969fe4da17caryclark } 28755888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fEndSpan) { 28855888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 28955888e44171ffd48b591d19256884a969fe4da17caryclark } 29055888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSpan) { 29155888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppSpan=%d", glitch.fOppSpan->debugID()); 29255888e44171ffd48b591d19256884a969fe4da17caryclark } 29355888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppEndSpan) { 29455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 29555888e44171ffd48b591d19256884a969fe4da17caryclark } 29655888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fStartT)) { 29755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" startT=%g", glitch.fStartT); 29855888e44171ffd48b591d19256884a969fe4da17caryclark } 29955888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fEndT)) { 30055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" endT=%g", glitch.fEndT); 30155888e44171ffd48b591d19256884a969fe4da17caryclark } 30255888e44171ffd48b591d19256884a969fe4da17caryclark if (glitch.fOppSegment) { 30355888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 30455888e44171ffd48b591d19256884a969fe4da17caryclark } 30555888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppStartT)) { 30655888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppStartT=%g", glitch.fOppStartT); 30755888e44171ffd48b591d19256884a969fe4da17caryclark } 30855888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fOppEndT)) { 30955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" oppEndT=%g", glitch.fOppEndT); 31055888e44171ffd48b591d19256884a969fe4da17caryclark } 31155888e44171ffd48b591d19256884a969fe4da17caryclark if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 31255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 31355888e44171ffd48b591d19256884a969fe4da17caryclark } 31455888e44171ffd48b591d19256884a969fe4da17caryclark switch (glitch.fType) { 31555888e44171ffd48b591d19256884a969fe4da17caryclark case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 31655888e44171ffd48b591d19256884a969fe4da17caryclark case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 31755888e44171ffd48b591d19256884a969fe4da17caryclark case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 31855888e44171ffd48b591d19256884a969fe4da17caryclark case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 31955888e44171ffd48b591d19256884a969fe4da17caryclark case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 32055888e44171ffd48b591d19256884a969fe4da17caryclark case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 32155888e44171ffd48b591d19256884a969fe4da17caryclark case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 32255888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 32355888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 32455888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 32555888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 32655888e44171ffd48b591d19256884a969fe4da17caryclark case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 32755888e44171ffd48b591d19256884a969fe4da17caryclark case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 32855888e44171ffd48b591d19256884a969fe4da17caryclark case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 32955888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 33055888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 33155888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 33255888e44171ffd48b591d19256884a969fe4da17caryclark case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 33355888e44171ffd48b591d19256884a969fe4da17caryclark case kMergeContained_Glitch: SkDebugf(" MergeContained"); break; 33455888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 33555888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 33655888e44171ffd48b591d19256884a969fe4da17caryclark case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 33755888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 33855888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 33955888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 34055888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 34155888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 34255888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 34355888e44171ffd48b591d19256884a969fe4da17caryclark case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 34455888e44171ffd48b591d19256884a969fe4da17caryclark case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 34555888e44171ffd48b591d19256884a969fe4da17caryclark case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 34655888e44171ffd48b591d19256884a969fe4da17caryclark case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 34755888e44171ffd48b591d19256884a969fe4da17caryclark case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 34855888e44171ffd48b591d19256884a969fe4da17caryclark default: SkASSERT(0); 34955888e44171ffd48b591d19256884a969fe4da17caryclark } 35055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("\n"); 35155888e44171ffd48b591d19256884a969fe4da17caryclark } 35255888e44171ffd48b591d19256884a969fe4da17caryclark contourList->globalState()->debugSetCheckHealth(false); 35355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_ACTIVE_SPANS 35455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("active after %s:\n", id); 35555888e44171ffd48b591d19256884a969fe4da17caryclark ShowActiveSpans(contourList); 35655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 35755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 35926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 3604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 362570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 36307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 36407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 36507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 36607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 37007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 37107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 37207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 37307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 37507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 37607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 37707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 37807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 379570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 38007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 383570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 38507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 38607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 38707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 38807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 38907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 39054359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 39154359294a7c9dc54802d512a5d891a35c1663392caryclark 392a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 39307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 394385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 395cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 396385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 397a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 398570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 39907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 40007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 40107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 40207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 40307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 40407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 40507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 40607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 40707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 40807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 40907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 41007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 41107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 412a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 413a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 414570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4151049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 4161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 4171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 4181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 4191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 4201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 4211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 4221049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 4231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 4241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 4251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 42655888e44171ffd48b591d19256884a969fe4da17caryclark "kXOR_PathOp", 4271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 4281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 4291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 43003b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 43103b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 43203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 43303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 4341049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 4351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 4361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 4371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 4381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 439086eea93b1f8253420c233c33cdabc0e74b08091reedSK_DECLARE_STATIC_MUTEX(gTestMutex); 4401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 4411049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 4421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 4431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 4441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 4451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 4461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 4471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 4484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 45027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 45126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 45226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 45326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 45426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 45526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 45626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 45726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 45826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 45926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 46026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 46126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 46226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 46326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 46426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 46526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 46626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 46826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 46926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 47026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 47126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 47226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 47326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 47426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 47526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 47626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 47726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 47826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 47926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 48026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 48326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 48426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 48526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 48626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 48726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 48826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 49026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 49126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 49226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 49326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 49426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 49526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 49626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 49726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 49826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 49926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 50026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 50126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 50226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 50326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 50426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 50526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 50626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 50726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 50826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 50926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 51026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 51126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 51226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 51526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 51626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 51726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 51826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 51926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 52026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 52126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 52226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 52326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 52426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 52526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 52626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 52826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 52926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 53026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 53126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 53226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 53326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 53426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 53526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 53627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 53727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG 53827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const { 53927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE 54027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return FLAGS_runFail; 54127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else 54227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 54327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 54427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 54527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 54627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 54726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 54826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 54926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 55026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 55126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 55226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 55326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 55426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 55526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 55626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 55726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 55826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 55926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 56026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 561624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 562624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsQuad.h" 563624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 564624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 565624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 566624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 567624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 568624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 569624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 570624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 571624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 572624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 573624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 574624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 575624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 576ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 577ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 578ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 579ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 5804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 581570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 582570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 58455888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with addT() 58555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* SkOpSegment::debugAddT(double t, AliasMatch allowAlias, bool* allocated) const { 58655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 58755888e44171ffd48b591d19256884a969fe4da17caryclark SkPoint pt = this->ptAtT(t); 58855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* span = &fHead; 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 59055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* result = span->ptT(); 59155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* loop; 59255888e44171ffd48b591d19256884a969fe4da17caryclark bool duplicatePt; 59355888e44171ffd48b591d19256884a969fe4da17caryclark if (t == result->fT) { 59455888e44171ffd48b591d19256884a969fe4da17caryclark goto bumpSpan; 59555888e44171ffd48b591d19256884a969fe4da17caryclark } 59655888e44171ffd48b591d19256884a969fe4da17caryclark if (this->match(result, this, t, pt, allowAlias)) { 59755888e44171ffd48b591d19256884a969fe4da17caryclark // see if any existing alias matches segment, pt, and t 59855888e44171ffd48b591d19256884a969fe4da17caryclark loop = result->next(); 59955888e44171ffd48b591d19256884a969fe4da17caryclark duplicatePt = false; 60055888e44171ffd48b591d19256884a969fe4da17caryclark while (loop != result) { 60155888e44171ffd48b591d19256884a969fe4da17caryclark bool ptMatch = loop->fPt == pt; 60255888e44171ffd48b591d19256884a969fe4da17caryclark if (loop->segment() == this && loop->fT == t && ptMatch) { 60355888e44171ffd48b591d19256884a969fe4da17caryclark goto bumpSpan; 60426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60555888e44171ffd48b591d19256884a969fe4da17caryclark duplicatePt |= ptMatch; 60655888e44171ffd48b591d19256884a969fe4da17caryclark loop = loop->next(); 60726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 60855888e44171ffd48b591d19256884a969fe4da17caryclark if (kNoAliasMatch == allowAlias) { 60955888e44171ffd48b591d19256884a969fe4da17caryclark bumpSpan: 61055888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 61155888e44171ffd48b591d19256884a969fe4da17caryclark return result; 61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61355888e44171ffd48b591d19256884a969fe4da17caryclark// SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator); 61455888e44171ffd48b591d19256884a969fe4da17caryclark// alias->init(result->span(), t, pt, duplicatePt); 61555888e44171ffd48b591d19256884a969fe4da17caryclark// result->insert(alias); 61655888e44171ffd48b591d19256884a969fe4da17caryclark// result->span()->unaligned(); 61755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 61855888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 61955888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 62055888e44171ffd48b591d19256884a969fe4da17caryclark// alias->segment()->debugID(), alias->span()->debugID()); 62155888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 62255888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 62355888e44171ffd48b591d19256884a969fe4da17caryclark if (allocated) { 62455888e44171ffd48b591d19256884a969fe4da17caryclark *allocated = true; 62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62655888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 62755888e44171ffd48b591d19256884a969fe4da17caryclark } 62855888e44171ffd48b591d19256884a969fe4da17caryclark if (t < result->fT) { 62955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = result->span()->prev(); 63055888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev) { 63155888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; // FIXME: this is a fail case; nullptr return elsewhere means result was allocated in non-const version 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63355888e44171ffd48b591d19256884a969fe4da17caryclark// SkOpSpan* span = insert(prev, allocator); 63455888e44171ffd48b591d19256884a969fe4da17caryclark// span->init(this, prev, t, pt); 63555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 63655888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ADD_T 63755888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 63855888e44171ffd48b591d19256884a969fe4da17caryclark// span->segment()->debugID(), span->debugID()); 63955888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 64055888e44171ffd48b591d19256884a969fe4da17caryclark// span->bumpSpanAdds(); 64155888e44171ffd48b591d19256884a969fe4da17caryclark if (allocated) { 64255888e44171ffd48b591d19256884a969fe4da17caryclark *allocated = true; 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64455888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 64555888e44171ffd48b591d19256884a969fe4da17caryclark } 64655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(span != &fTail); 64755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->upCast()->next())); 64855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 64955888e44171ffd48b591d19256884a969fe4da17caryclark return nullptr; 65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 65955888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 66755888e44171ffd48b591d19256884a969fe4da17caryclark if (angle && angle->debugCheckCoincidence()) { 66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 66926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 67026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 67126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 67226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 67326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 67455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 67526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 67626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 67726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveMultiples(id, glitches); 67826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveNearby(id, glitches); 67955888e44171ffd48b591d19256884a969fe4da17caryclark debugMissingCoincidence(id, glitches); 68055888e44171ffd48b591d19256884a969fe4da17caryclark} 68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 68255888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearAll() 68355888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearAll(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 68455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* span = &fHead; 68555888e44171ffd48b591d19256884a969fe4da17caryclark do { 68655888e44171ffd48b591d19256884a969fe4da17caryclark this->debugClearOne(span, id, glitches); 68755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((span = span->next()->upCastable())); 68855888e44171ffd48b591d19256884a969fe4da17caryclark this->globalState()->coincidence()->debugRelease(id, glitches, this); 68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 69155888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with clearOne() 69255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugClearOne(const SkOpSpan* span, const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 69355888e44171ffd48b591d19256884a969fe4da17caryclark if (span->windValue()) glitches->record(kCollapsedWindValue_Glitch, id, span); 69455888e44171ffd48b591d19256884a969fe4da17caryclark if (span->oppValue()) glitches->record(kCollapsedOppValue_Glitch, id, span); 69555888e44171ffd48b591d19256884a969fe4da17caryclark if (!span->done()) glitches->record(kCollapsedDone_Glitch, id, span); 69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 69954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 70096fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 70154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 70254359294a7c9dc54802d512a5d891a35c1663392caryclark do { 70354359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 704dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 70554359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 706dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 70754359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 708dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 709dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 710dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 711dac1d17027dcaa5596885a9f333979418b35001ccaryclark 71226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 71355888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with ClearVisited 71455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 71555888e44171ffd48b591d19256884a969fe4da17caryclark // reset visited flag back to false 71655888e44171ffd48b591d19256884a969fe4da17caryclark do { 71755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 71855888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != stopPtT) { 71955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->segment(); 72055888e44171ffd48b591d19256884a969fe4da17caryclark opp->resetDebugVisited(); 72155888e44171ffd48b591d19256884a969fe4da17caryclark } 72255888e44171ffd48b591d19256884a969fe4da17caryclark } while (!span->final() && (span = span->upCast()->next())); 72355888e44171ffd48b591d19256884a969fe4da17caryclark} 72455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 72555888e44171ffd48b591d19256884a969fe4da17caryclark 72655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 72755888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with missingCoincidence() 72855888e44171ffd48b591d19256884a969fe4da17caryclark// look for pairs of undetected coincident curves 72955888e44171ffd48b591d19256884a969fe4da17caryclark// assumes that segments going in have visited flag clear 73055888e44171ffd48b591d19256884a969fe4da17caryclark// Even though pairs of curves correct detect coincident runs, a run may be missed 73155888e44171ffd48b591d19256884a969fe4da17caryclark// if the coincidence is a product of multiple intersections. For instance, given 73255888e44171ffd48b591d19256884a969fe4da17caryclark// curves A, B, and C: 73355888e44171ffd48b591d19256884a969fe4da17caryclark// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 73455888e44171ffd48b591d19256884a969fe4da17caryclark// the end of C that the intersection is replaced with the end of C. 73555888e44171ffd48b591d19256884a969fe4da17caryclark// Even though A-B correctly do not detect an intersection at point 2, 73655888e44171ffd48b591d19256884a969fe4da17caryclark// the resulting run from point 1 to point 2 is coincident on A and B. 73755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 73826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 73926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 74026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 74126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 74226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 74355888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 74426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 74526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 74626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 74726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 74826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 74926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* opp = ptT->span()->segment(); 75226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 75326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 75655888e44171ffd48b591d19256884a969fe4da17caryclark if (!opp->debugVisited()) { 75726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 76255888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this) { 76355888e44171ffd48b591d19256884a969fe4da17caryclark continue; 76455888e44171ffd48b591d19256884a969fe4da17caryclark } 76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 76855888e44171ffd48b591d19256884a969fe4da17caryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77155888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 77355888e44171ffd48b591d19256884a969fe4da17caryclark } 77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* segment = priorPtT->span()->segment(); 78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 79226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 79655888e44171ffd48b591d19256884a969fe4da17caryclark if (priorPtT == ptT) { 79755888e44171ffd48b591d19256884a969fe4da17caryclark continue; 79855888e44171ffd48b591d19256884a969fe4da17caryclark } 79926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 80126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 80226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 80326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 80426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 80526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 80655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 80755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 80855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootPtT = ptT->span()->ptT(); 80955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 81055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 81155888e44171ffd48b591d19256884a969fe4da17caryclark if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 81226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 81326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 81455888e44171ffd48b591d19256884a969fe4da17caryclark if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 81555888e44171ffd48b591d19256884a969fe4da17caryclark // mark coincidence 81655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 81755888e44171ffd48b591d19256884a969fe4da17caryclark// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 81855888e44171ffd48b591d19256884a969fe4da17caryclark// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 81955888e44171ffd48b591d19256884a969fe4da17caryclark// rootOppEnd->debugID()); 82055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, oppEnd); 82255888e44171ffd48b591d19256884a969fe4da17caryclark // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 82355888e44171ffd48b591d19256884a969fe4da17caryclark // } 82455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 825d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 82655888e44171ffd48b591d19256884a969fe4da17caryclark#endif 82755888e44171ffd48b591d19256884a969fe4da17caryclark // result = true; 82826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 82926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 83026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 83126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 83226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 83555888e44171ffd48b591d19256884a969fe4da17caryclark DebugClearVisited(&fHead); 83655888e44171ffd48b591d19256884a969fe4da17caryclark return; 83726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 83826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 83955888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveMultiples() 84055888e44171ffd48b591d19256884a969fe4da17caryclark// if a span has more than one intersection, merge the other segments' span as needed 84126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 84255888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 84326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 84426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 84526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 84626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(addCount >= 1); 84726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (addCount == 1) { 84826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 84926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 85126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 85226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 85326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 85426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 85526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 85626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 85726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 85826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 85926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 86126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 86226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 86326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 86426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 86526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 86626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 86726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 86826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 86926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 87026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 87226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 87526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 87626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 87826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 87926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 88026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 88126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 88226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 88326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 88426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 88626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 88726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 88826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 88926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 89126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 89226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 89326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 89426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 89526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 89626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 89726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 89826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 89926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 90026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 90126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 90226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 90326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 90426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 90526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 90626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 90726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 90826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 90926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 91126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 91226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 91326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 91426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 91526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 91626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 91726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 91855888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 91926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) { 92026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse 92126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(oppSpan != &oppSegment->fTail); 92226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kMoveMultiple_Glitch, id, oppTest, oppSpan); 92326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 92426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppTest); 92526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 92655888e44171ffd48b591d19256884a969fe4da17caryclark oppSegment->debugValidate(); 92726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 92826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 92955888e44171ffd48b591d19256884a969fe4da17caryclark tryNextSpan: 93026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 93126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 93226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 93355888e44171ffd48b591d19256884a969fe4da17caryclarkcheckNextSpan: 93426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 93526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 93655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 93755888e44171ffd48b591d19256884a969fe4da17caryclark return; 93826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 93926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 94055888e44171ffd48b591d19256884a969fe4da17caryclark// commented-out lines keep this in sync with moveNearby() 94155888e44171ffd48b591d19256884a969fe4da17caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 94226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 94355888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 94455888e44171ffd48b591d19256884a969fe4da17caryclark // release undeleted spans pointing to this seg that are linked to the primary span 94555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* spanBase = &fHead; 94626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 94755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = spanBase->ptT(); 94855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* headPtT = ptT; 94955888e44171ffd48b591d19256884a969fe4da17caryclark while ((ptT = ptT->next()) != headPtT) { 95055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = ptT->span(); 95155888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() == this && !ptT->deleted() && test != spanBase 95255888e44171ffd48b591d19256884a969fe4da17caryclark && test->ptT() == ptT) { 95355888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 95455888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase == &fHead) { 95555888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyClearAll_Glitch, id, this); 95655888e44171ffd48b591d19256884a969fe4da17caryclark// return; 95755888e44171ffd48b591d19256884a969fe4da17caryclark } 95855888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyReleaseFinal_Glitch, id, spanBase, ptT); 95955888e44171ffd48b591d19256884a969fe4da17caryclark } else if (test->prev()) { 96055888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyRelease_Glitch, id, test, headPtT); 96155888e44171ffd48b591d19256884a969fe4da17caryclark } 96255888e44171ffd48b591d19256884a969fe4da17caryclark// break; 96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 96555888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = spanBase->upCast()->next(); 96655888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 96755888e44171ffd48b591d19256884a969fe4da17caryclark 96855888e44171ffd48b591d19256884a969fe4da17caryclark // This loop looks for adjacent spans which are near by 96955888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = &fHead; 97055888e44171ffd48b591d19256884a969fe4da17caryclark do { // iterate through all spans associated with start 97155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* test = spanBase->upCast()->next(); 97255888e44171ffd48b591d19256884a969fe4da17caryclark if (this->spansNearby(spanBase, test)) { 97355888e44171ffd48b591d19256884a969fe4da17caryclark if (test->final()) { 97455888e44171ffd48b591d19256884a969fe4da17caryclark if (spanBase->prev()) { 97555888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyMergeFinal_Glitch, id, test); 97655888e44171ffd48b591d19256884a969fe4da17caryclark } else { 97755888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyClearAll2_Glitch, id, this); 97855888e44171ffd48b591d19256884a969fe4da17caryclark // return 97955888e44171ffd48b591d19256884a969fe4da17caryclark } 98055888e44171ffd48b591d19256884a969fe4da17caryclark } else { 98155888e44171ffd48b591d19256884a969fe4da17caryclark glitches->record(kMoveNearbyMerge_Glitch, id, spanBase); 98255888e44171ffd48b591d19256884a969fe4da17caryclark } 98355888e44171ffd48b591d19256884a969fe4da17caryclark } 98455888e44171ffd48b591d19256884a969fe4da17caryclark spanBase = test; 98555888e44171ffd48b591d19256884a969fe4da17caryclark } while (!spanBase->final()); 98655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 9911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 9924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 9934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 99454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 9954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const { 9964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 9974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 9984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 9994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 10014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 100254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 100354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 100454359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 10054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 10064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 10084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 10094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 101154359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 10121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); 101355888e44171ffd48b591d19256884a969fe4da17caryclark // since endpoints may have be adjusted, show actual computed curves 101455888e44171ffd48b591d19256884a969fe4da17caryclark SkDCurve curvePart; 101555888e44171ffd48b591d19256884a969fe4da17caryclark this->subDivide(span, span->next(), &curvePart); 101655888e44171ffd48b591d19256884a969fe4da17caryclark const SkDPoint* pts = curvePart.fCubic.fPts; 101755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 10184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 101955888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 10204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 102255888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(" %1.9gf", curvePart.fConic.fWeight); 10231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 102455888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 102554359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 1026624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=?"); 10274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1028624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=%d", span->windSum()); 1029624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1030624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 1031624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=?"); 1032624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1033624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=%d", span->oppSum()); 1034624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1035624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windValue=%d", span->windValue()); 1036624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 1037624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppValue=%d", span->oppValue()); 10384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 103954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 104054359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 104454359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 104554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 104654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 10471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 10484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 10494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 10504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 10514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 105254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 105354359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 105454359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 10554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 105754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 10584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 105954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 106054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 106154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 106254359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 106354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 106454359294a7c9dc54802d512a5d891a35c1663392caryclark } 106554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 10664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 106854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 10694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 107054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 10711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 10724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 10734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 10744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 10754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 107654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 107754359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 107854359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 107954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 108054359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 108154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 108254359294a7c9dc54802d512a5d891a35c1663392caryclark } 108354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 108454359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 108554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 108654359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 108754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 108854359294a7c9dc54802d512a5d891a35c1663392caryclark } 108954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 109054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 10914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 109354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 10944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 109654359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 10974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 109954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 11004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 110154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 11024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 110354359294a7c9dc54802d512a5d891a35c1663392caryclark 11044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 11054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 110626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 110726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 110826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 110955888e44171ffd48b591d19256884a969fe4da17caryclark This checks the distance between start points; the distance between 111026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 111426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 111526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 111626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 111726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 111826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 111926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 112026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 112126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 112226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 112326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 112426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 112526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 112626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 112726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 112826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 112926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 113026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 113126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 113226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 113326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 113426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 113526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 113626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 113726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 113826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 113926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 114026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 114126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 114226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 114326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 114426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 114526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 114626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 114755888e44171ffd48b591d19256884a969fe4da17caryclark } while (test->fNext != this); 114826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 114926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 115026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 115154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 115254359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 115354359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 115454359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 115554359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 115654359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart), 115754359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 115854359294a7c9dc54802d512a5d891a35c1663392caryclark break; 115954359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 116054359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart), 116154359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 116254359294a7c9dc54802d512a5d891a35c1663392caryclark break; 11631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 11641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 11651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark CONIC_DEBUG_DATA(fCurvePart, fCurvePart.fConic.fWeight), 11661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 11671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 116854359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 116954359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart), 117054359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 117154359294a7c9dc54802d512a5d891a35c1663392caryclark break; 117254359294a7c9dc54802d512a5d891a35c1663392caryclark default: 117354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 11741b24933e52f50773de29332387a12721811f3012mtklein } 117554359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 117654359294a7c9dc54802d512a5d891a35c1663392caryclark} 117754359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 117854359294a7c9dc54802d512a5d891a35c1663392caryclark 1179624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 118054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 118154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 118254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 118354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 118454359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 118554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 118654359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 118754359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 118854359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 118954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 119054359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 119154359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 119254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1193ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1194ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1195ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 119654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 119755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 119855888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 119955888e44171ffd48b591d19256884a969fe4da17caryclark return; 120055888e44171ffd48b591d19256884a969fe4da17caryclark } 120155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 120254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 120354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 120454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 120554359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 120654359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 120754359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 120854359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 120954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 121054359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 121154359294a7c9dc54802d512a5d891a35c1663392caryclark return; 121254359294a7c9dc54802d512a5d891a35c1663392caryclark } 121354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 121454359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 121554359294a7c9dc54802d512a5d891a35c1663392caryclark return; 121654359294a7c9dc54802d512a5d891a35c1663392caryclark } 121754359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 121854359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 121954359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 122054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 122154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 122254359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 122354359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 122454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 122554359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1226624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 122754359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 122854359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 122954359294a7c9dc54802d512a5d891a35c1663392caryclark } 123054359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 123154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 123254359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1233624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 123454359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 123554359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 123654359294a7c9dc54802d512a5d891a35c1663392caryclark } 123754359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 123854359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1239182b499cd75c971f85cdf52c1827b3c220cc9011caryclark SkASSERT(wind == 0 || !FLAGS_runFail); 124054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(opp == 0 || !FLAGS_runFail); 124154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 124254359294a7c9dc54802d512a5d891a35c1663392caryclark} 124354359294a7c9dc54802d512a5d891a35c1663392caryclark 124454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 124554359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 124654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 124754359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 124854359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 124954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1250f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 125154359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 125254359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 125354359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 125454359294a7c9dc54802d512a5d891a35c1663392caryclark break; 125554359294a7c9dc54802d512a5d891a35c1663392caryclark } 1256f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 125754359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 125854359294a7c9dc54802d512a5d891a35c1663392caryclark return; 125954359294a7c9dc54802d512a5d891a35c1663392caryclark } 126054359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 126154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 126254359294a7c9dc54802d512a5d891a35c1663392caryclark} 126354359294a7c9dc54802d512a5d891a35c1663392caryclark 126455888e44171ffd48b591d19256884a969fe4da17caryclark#ifdef SK_DEBUG 126555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 126655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpGlobalState* debugState) const { 126755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail()); 126855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail()); 126955888e44171ffd48b591d19256884a969fe4da17caryclark} 127055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 127255888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 127355888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with expand */ 127455888e44171ffd48b591d19256884a969fe4da17caryclarkbool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const { 127555888e44171ffd48b591d19256884a969fe4da17caryclark bool expanded = false; 127655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = coinPtTStart()->segment(); 127755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSegment = oppPtTStart()->segment(); 127855888e44171ffd48b591d19256884a969fe4da17caryclark do { 127955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coinPtTStart()->span()->upCast(); 128055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* prev = start->prev(); 128155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 128255888e44171ffd48b591d19256884a969fe4da17caryclark if (!prev || !(oppPtT = prev->contains(oppSegment))) { 128355888e44171ffd48b591d19256884a969fe4da17caryclark break; 128455888e44171ffd48b591d19256884a969fe4da17caryclark } 128555888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (prev->t() + start->t()) / 2; 128655888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 128755888e44171ffd48b591d19256884a969fe4da17caryclark break; 128855888e44171ffd48b591d19256884a969fe4da17caryclark } 128955888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, this, prev->ptT(), oppPtT); 129055888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 129155888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 129255888e44171ffd48b591d19256884a969fe4da17caryclark do { 129355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coinPtTEnd()->span(); 129455888e44171ffd48b591d19256884a969fe4da17caryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 129555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtT; 129655888e44171ffd48b591d19256884a969fe4da17caryclark if (!next || !(oppPtT = next->contains(oppSegment))) { 129755888e44171ffd48b591d19256884a969fe4da17caryclark break; 129855888e44171ffd48b591d19256884a969fe4da17caryclark } 129955888e44171ffd48b591d19256884a969fe4da17caryclark double midT = (end->t() + next->t()) / 2; 130055888e44171ffd48b591d19256884a969fe4da17caryclark if (!segment->isClose(midT, oppSegment)) { 130155888e44171ffd48b591d19256884a969fe4da17caryclark break; 130255888e44171ffd48b591d19256884a969fe4da17caryclark } 130355888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, this, next->ptT(), oppPtT); 130455888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 130555888e44171ffd48b591d19256884a969fe4da17caryclark } while (false); // actual continues while expansion is possible 130655888e44171ffd48b591d19256884a969fe4da17caryclark return expanded; 130755888e44171ffd48b591d19256884a969fe4da17caryclark} 130855888e44171ffd48b591d19256884a969fe4da17caryclark 130955888e44171ffd48b591d19256884a969fe4da17caryclark#define FAIL_IF(cond) do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false) 131055888e44171ffd48b591d19256884a969fe4da17caryclark 131155888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addExpanded */ 131255888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident pair, match the spans 131355888e44171ffd48b591d19256884a969fe4da17caryclark// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 131426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* log) const { 131526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 131626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 1317ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1318ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 131926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 132055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* startPtT = coin->coinPtTStart(); 132155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oStartPtT = coin->oppPtTStart(); 132226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(startPtT->contains(oStartPtT)); 132355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 132426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 132526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 132655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 132755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 132855888e44171ffd48b591d19256884a969fe4da17caryclark FAIL_IF(oEnd->deleted()); 132926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 133055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 133155888e44171ffd48b591d19256884a969fe4da17caryclark if (!oTest) { 133255888e44171ffd48b591d19256884a969fe4da17caryclark return; 133355888e44171ffd48b591d19256884a969fe4da17caryclark } 133426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 133555888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->ptT()->contains(oTest->segment()) 133655888e44171ffd48b591d19256884a969fe4da17caryclark || !oTest->ptT()->contains(start->segment())) { 133726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 133855888e44171ffd48b591d19256884a969fe4da17caryclark double startRange = coin->coinPtTEnd()->fT - startPtT->fT; 133955888e44171ffd48b591d19256884a969fe4da17caryclark FAIL_IF(!startRange); 134026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double startPart = (test->t() - startPtT->fT) / startRange; 134155888e44171ffd48b591d19256884a969fe4da17caryclark double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT; 134255888e44171ffd48b591d19256884a969fe4da17caryclark FAIL_IF(!oStartRange); 134326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 134455888e44171ffd48b591d19256884a969fe4da17caryclark FAIL_IF(startPart == oStartPart); 134555888e44171ffd48b591d19256884a969fe4da17caryclark bool startOver = false; 134655888e44171ffd48b591d19256884a969fe4da17caryclark if (startPart < oStartPart) 134755888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddExpandedCoin_Glitch, id, // strange debug formatting lines up with original 134855888e44171ffd48b591d19256884a969fe4da17caryclark oStartPtT->fT + oStartRange * startPart, test); 134955888e44171ffd48b591d19256884a969fe4da17caryclark else log->record(kAddExpandedCoin_Glitch, id, 135055888e44171ffd48b591d19256884a969fe4da17caryclark startPtT->fT + startRange * oStartPart, oTest); 135155888e44171ffd48b591d19256884a969fe4da17caryclark if (false) { 135255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 135355888e44171ffd48b591d19256884a969fe4da17caryclark return; 135426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135555888e44171ffd48b591d19256884a969fe4da17caryclark if (startOver) { 135655888e44171ffd48b591d19256884a969fe4da17caryclark test = start; 135755888e44171ffd48b591d19256884a969fe4da17caryclark oTest = oStart; 135826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136055888e44171ffd48b591d19256884a969fe4da17caryclark if (test != end) { 136126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 136226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136355888e44171ffd48b591d19256884a969fe4da17caryclark if (oTest != oEnd) { 136455888e44171ffd48b591d19256884a969fe4da17caryclark oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 136555888e44171ffd48b591d19256884a969fe4da17caryclark if (!oTest) { 136655888e44171ffd48b591d19256884a969fe4da17caryclark return; 136755888e44171ffd48b591d19256884a969fe4da17caryclark } 136826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 137055888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 137155888e44171ffd48b591d19256884a969fe4da17caryclark return; 137255888e44171ffd48b591d19256884a969fe4da17caryclark} 137355888e44171ffd48b591d19256884a969fe4da17caryclark 137455888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync with addIfMissing() */ 137555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, 137655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog* log) const { 137755888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fTop); 137855888e44171ffd48b591d19256884a969fe4da17caryclark if (fTop && alreadyAdded(fTop, outer, over1s, over1e)) { // in debug, fTop may be null 137955888e44171ffd48b591d19256884a969fe4da17caryclark return; 138026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 138155888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && alreadyAdded(fHead, outer, over1s, over1e)) { 138255888e44171ffd48b591d19256884a969fe4da17caryclark return; 138355888e44171ffd48b591d19256884a969fe4da17caryclark } 138455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddIfMissingCoin_Glitch, id, outer->coinPtTStart(), outer->coinPtTEnd(), over1s, over1e); 138555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 138655888e44171ffd48b591d19256884a969fe4da17caryclark return; 138726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 138826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 138955888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addIfMissing() */ 139055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, 139155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd, 139255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 139355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, const char* id, SkPathOpsDebug::GlitchLog* log) const { 139426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 139555888e44171ffd48b591d19256884a969fe4da17caryclark TRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe); 139655888e44171ffd48b591d19256884a969fe4da17caryclark TRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe); 139755888e44171ffd48b591d19256884a969fe4da17caryclark bool swap = coinTs > coinTe; 139855888e44171ffd48b591d19256884a969fe4da17caryclark if (swap) { 139955888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 140026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { 140226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 140326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140455888e44171ffd48b591d19256884a969fe4da17caryclark if (swap) { 140526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 140626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = coinPtTStart->segment(); 140855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = oppPtTStart->segment(); 140955888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == oppSeg) { 141055888e44171ffd48b591d19256884a969fe4da17caryclark return; 141126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 141255888e44171ffd48b591d19256884a969fe4da17caryclark return this->debugAddOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, id, log); 141355888e44171ffd48b591d19256884a969fe4da17caryclark} 141455888e44171ffd48b591d19256884a969fe4da17caryclark 141555888e44171ffd48b591d19256884a969fe4da17caryclark/* Commented-out lines keep this in sync addOrOverlap() */ 141655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 141755888e44171ffd48b591d19256884a969fe4da17caryclark double coinTs, double coinTe, double oppTs, double oppTe, const char* id, SkPathOpsDebug::GlitchLog* log) const { 141855888e44171ffd48b591d19256884a969fe4da17caryclark SkTDArray<SkCoincidentSpans*> overlaps; 141955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!fTop); // this is (correctly) reversed in addifMissing() 142055888e44171ffd48b591d19256884a969fe4da17caryclark if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) { 142155888e44171ffd48b591d19256884a969fe4da17caryclark return; 142255888e44171ffd48b591d19256884a969fe4da17caryclark } 142355888e44171ffd48b591d19256884a969fe4da17caryclark if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 142455888e44171ffd48b591d19256884a969fe4da17caryclark coinTe, oppTs, oppTe, &overlaps)) { 142555888e44171ffd48b591d19256884a969fe4da17caryclark return; 142655888e44171ffd48b591d19256884a969fe4da17caryclark } 142755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 142855888e44171ffd48b591d19256884a969fe4da17caryclark for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 142955888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = overlaps[index]; 143055888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 143155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTStart()); 143255888e44171ffd48b591d19256884a969fe4da17caryclark } 143355888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 143455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->coinPtTEnd()); 143555888e44171ffd48b591d19256884a969fe4da17caryclark } 143655888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 143755888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 143855888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 143955888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTStart()); 144055888e44171ffd48b591d19256884a969fe4da17caryclark } 144155888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->flipped() 144255888e44171ffd48b591d19256884a969fe4da17caryclark ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 144355888e44171ffd48b591d19256884a969fe4da17caryclark : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 144455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd()); 144555888e44171ffd48b591d19256884a969fe4da17caryclark } 144655888e44171ffd48b591d19256884a969fe4da17caryclark if (!fHead) { 144755888e44171ffd48b591d19256884a969fe4da17caryclark SkAssertResult(true); 144855888e44171ffd48b591d19256884a969fe4da17caryclark } 144955888e44171ffd48b591d19256884a969fe4da17caryclark } 145055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 145155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 145255888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap && cs && ce && overlap->contains(cs, ce)) { 145355888e44171ffd48b591d19256884a969fe4da17caryclark return; 145455888e44171ffd48b591d19256884a969fe4da17caryclark } 145555888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(cs != ce || !cs); 145655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 145755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 145855888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap && os && oe && overlap->contains(os, oe)) { 145955888e44171ffd48b591d19256884a969fe4da17caryclark return; 146055888e44171ffd48b591d19256884a969fe4da17caryclark } 146155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !cs || !cs->deleted()); 146255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !os || !os->deleted()); 146355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !ce || !ce->deleted()); 146455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(true || !oe || !oe->deleted()); 146555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 146655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 146755888e44171ffd48b591d19256884a969fe4da17caryclark if (csExisting && csExisting == ceExisting) { 146855888e44171ffd48b591d19256884a969fe4da17caryclark return; 146955888e44171ffd48b591d19256884a969fe4da17caryclark } 147055888e44171ffd48b591d19256884a969fe4da17caryclark if (csExisting && (csExisting == ce || csExisting->contains(ceExisting ? ceExisting : ce))) { 147155888e44171ffd48b591d19256884a969fe4da17caryclark return; 147255888e44171ffd48b591d19256884a969fe4da17caryclark } 147355888e44171ffd48b591d19256884a969fe4da17caryclark if (ceExisting && (ceExisting == cs || ceExisting->contains(csExisting ? csExisting : cs))) { 147455888e44171ffd48b591d19256884a969fe4da17caryclark return; 147555888e44171ffd48b591d19256884a969fe4da17caryclark } 147655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 147755888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 147855888e44171ffd48b591d19256884a969fe4da17caryclark if (osExisting && osExisting == oeExisting) { 147955888e44171ffd48b591d19256884a969fe4da17caryclark return; 148055888e44171ffd48b591d19256884a969fe4da17caryclark } 148155888e44171ffd48b591d19256884a969fe4da17caryclark if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeExisting : oe))) { 148255888e44171ffd48b591d19256884a969fe4da17caryclark return; 148355888e44171ffd48b591d19256884a969fe4da17caryclark } 148455888e44171ffd48b591d19256884a969fe4da17caryclark if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osExisting : os))) { 148555888e44171ffd48b591d19256884a969fe4da17caryclark return; 148655888e44171ffd48b591d19256884a969fe4da17caryclark } 148755888e44171ffd48b591d19256884a969fe4da17caryclark bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 148855888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 148955888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !os) { 149055888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs) 149155888e44171ffd48b591d19256884a969fe4da17caryclark cs = coinSeg->debugAddT(coinTs, SkOpSegment::kNoAliasMatch, nullptr); 149255888e44171ffd48b591d19256884a969fe4da17caryclark if (!os) 149355888e44171ffd48b591d19256884a969fe4da17caryclark os = oppSeg->debugAddT(oppTs, SkOpSegment::kNoAliasMatch, nullptr); 149455888e44171ffd48b591d19256884a969fe4da17caryclark if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDeleted, &osDeleted); 149555888e44171ffd48b591d19256884a969fe4da17caryclark// cs = csWritable; 149655888e44171ffd48b591d19256884a969fe4da17caryclark// os = osWritable; 149755888e44171ffd48b591d19256884a969fe4da17caryclark if ((ce && ce->deleted()) || (oe && oe->deleted())) { 149855888e44171ffd48b591d19256884a969fe4da17caryclark return; 149955888e44171ffd48b591d19256884a969fe4da17caryclark } 150055888e44171ffd48b591d19256884a969fe4da17caryclark } 150155888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce || !oe) { 150255888e44171ffd48b591d19256884a969fe4da17caryclark if (!ce) 150355888e44171ffd48b591d19256884a969fe4da17caryclark ce = coinSeg->debugAddT(coinTe, SkOpSegment::kNoAliasMatch, nullptr); 150455888e44171ffd48b591d19256884a969fe4da17caryclark if (!oe) 150555888e44171ffd48b591d19256884a969fe4da17caryclark oe = oppSeg->debugAddT(oppTe, SkOpSegment::kNoAliasMatch, nullptr); 150655888e44171ffd48b591d19256884a969fe4da17caryclark if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDeleted, &oeDeleted); 150755888e44171ffd48b591d19256884a969fe4da17caryclark// ce = ceWritable; 150855888e44171ffd48b591d19256884a969fe4da17caryclark// oe = oeWritable; 150955888e44171ffd48b591d19256884a969fe4da17caryclark } 151055888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 151155888e44171ffd48b591d19256884a969fe4da17caryclark if (csDeleted || osDeleted || ceDeleted || oeDeleted) { 151255888e44171ffd48b591d19256884a969fe4da17caryclark return; 151355888e44171ffd48b591d19256884a969fe4da17caryclark } 151455888e44171ffd48b591d19256884a969fe4da17caryclark if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) { 151555888e44171ffd48b591d19256884a969fe4da17caryclark return; 151655888e44171ffd48b591d19256884a969fe4da17caryclark } 151755888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = true; 151855888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap) { 151955888e44171ffd48b591d19256884a969fe4da17caryclark if (overlap->coinPtTStart()->segment() == coinSeg) { 152055888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 152155888e44171ffd48b591d19256884a969fe4da17caryclark } else { 152255888e44171ffd48b591d19256884a969fe4da17caryclark if (oppTs > oppTe) { 152355888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(coinTs, coinTe); 152455888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(oppTs, oppTe); 152555888e44171ffd48b591d19256884a969fe4da17caryclark } 152655888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 152755888e44171ffd48b591d19256884a969fe4da17caryclark } 152855888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 152955888e44171ffd48b591d19256884a969fe4da17caryclark// if (result) { 153055888e44171ffd48b591d19256884a969fe4da17caryclark// overlap->debugShow(); 153155888e44171ffd48b591d19256884a969fe4da17caryclark// } 153255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 153355888e44171ffd48b591d19256884a969fe4da17caryclark } else { 153455888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kAddMissingCoin_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 153555888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 153655888e44171ffd48b591d19256884a969fe4da17caryclark// fHead->debugShow(); 153755888e44171ffd48b591d19256884a969fe4da17caryclark#endif 153855888e44171ffd48b591d19256884a969fe4da17caryclark } 153955888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 154055888e44171ffd48b591d19256884a969fe4da17caryclark return; 154126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 154226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 154355888e44171ffd48b591d19256884a969fe4da17caryclark// Extra commented-out lines keep this in sync with addMissing() 154455888e44171ffd48b591d19256884a969fe4da17caryclark/* detects overlaps of different coincident runs on same segment */ 154555888e44171ffd48b591d19256884a969fe4da17caryclark/* does not detect overlaps for pairs without any segments in common */ 154655888e44171ffd48b591d19256884a969fe4da17caryclark// returns true if caller should loop again 154726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const { 154826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 154926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 155026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 155126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 155255888e44171ffd48b591d19256884a969fe4da17caryclark // bool added = false; 155355888e44171ffd48b591d19256884a969fe4da17caryclark // fTop = outer; 155455888e44171ffd48b591d19256884a969fe4da17caryclark // fHead = nullptr; 155526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 155626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 155726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 155826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 155955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* outerCoin = outer->coinPtTStart()->segment(); 156055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* outerOpp = outer->oppPtTStart()->segment(); 156155888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin->done() || outerOpp->done()) { 156255888e44171ffd48b591d19256884a969fe4da17caryclark continue; 156355888e44171ffd48b591d19256884a969fe4da17caryclark } 156426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 156555888e44171ffd48b591d19256884a969fe4da17caryclark while ((inner = inner->next())) { 156655888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 156726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 156855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* innerCoin = inner->coinPtTStart()->segment(); 156955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* innerOpp = inner->oppPtTStart()->segment(); 157055888e44171ffd48b591d19256884a969fe4da17caryclark if (innerCoin->done() || innerOpp->done()) { 157155888e44171ffd48b591d19256884a969fe4da17caryclark continue; 157255888e44171ffd48b591d19256884a969fe4da17caryclark } 157355888e44171ffd48b591d19256884a969fe4da17caryclark if (outerCoin == innerCoin) { 157455888e44171ffd48b591d19256884a969fe4da17caryclark if (outerOpp != innerOpp 157555888e44171ffd48b591d19256884a969fe4da17caryclark && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(), 157655888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) { 157755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(), 157855888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE, 157955888e44171ffd48b591d19256884a969fe4da17caryclark outer->oppPtTStart(), outer->oppPtTEnd(), 158055888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), id, log); 158126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 158255888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerCoin == innerOpp) { 158355888e44171ffd48b591d19256884a969fe4da17caryclark if (outerOpp != innerCoin 158455888e44171ffd48b591d19256884a969fe4da17caryclark && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(), 158555888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) { 158655888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(), 158755888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE, 158855888e44171ffd48b591d19256884a969fe4da17caryclark outer->oppPtTStart(), outer->oppPtTEnd(), 158955888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), id, log); 159026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 159155888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerCoin) { 159255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerOpp); 159355888e44171ffd48b591d19256884a969fe4da17caryclark if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), 159455888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) { 159555888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(), 159655888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE, 159755888e44171ffd48b591d19256884a969fe4da17caryclark outer->coinPtTStart(), outer->coinPtTEnd(), 159855888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), id, log); 159926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 160055888e44171ffd48b591d19256884a969fe4da17caryclark } else if (outerOpp == innerOpp) { 160155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(outerCoin != innerCoin); 160255888e44171ffd48b591d19256884a969fe4da17caryclark if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(), 160355888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) { 160455888e44171ffd48b591d19256884a969fe4da17caryclark this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(), 160555888e44171ffd48b591d19256884a969fe4da17caryclark inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE, 160655888e44171ffd48b591d19256884a969fe4da17caryclark outer->coinPtTStart(), outer->coinPtTEnd(), 160755888e44171ffd48b591d19256884a969fe4da17caryclark inner->coinPtTStart(), inner->coinPtTEnd(), id, log); 160826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 160926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 161055888e44171ffd48b591d19256884a969fe4da17caryclark this->debugValidate(); 161155888e44171ffd48b591d19256884a969fe4da17caryclark } 161255888e44171ffd48b591d19256884a969fe4da17caryclark } while ((outer = outer->next())); 161355888e44171ffd48b591d19256884a969fe4da17caryclark // this->restoreHead(); 161455888e44171ffd48b591d19256884a969fe4da17caryclark return; 161555888e44171ffd48b591d19256884a969fe4da17caryclark} 161655888e44171ffd48b591d19256884a969fe4da17caryclark 161755888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with release() 161855888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 161955888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 162055888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 162155888e44171ffd48b591d19256884a969fe4da17caryclark return; 162255888e44171ffd48b591d19256884a969fe4da17caryclark } 162355888e44171ffd48b591d19256884a969fe4da17caryclark do { 162455888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->segment() == deleted 162555888e44171ffd48b591d19256884a969fe4da17caryclark || coin->coinPtTEnd()->segment() == deleted 162655888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTStart()->segment() == deleted 162755888e44171ffd48b591d19256884a969fe4da17caryclark || coin->oppPtTEnd()->segment() == deleted) { 162855888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kReleasedSpan_Glitch, id, coin); 162955888e44171ffd48b591d19256884a969fe4da17caryclark } 163055888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 163155888e44171ffd48b591d19256884a969fe4da17caryclark} 163255888e44171ffd48b591d19256884a969fe4da17caryclark 163355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with reorder() 163455888e44171ffd48b591d19256884a969fe4da17caryclark// iterate through all coincident pairs, looking for ranges greater than 1 163555888e44171ffd48b591d19256884a969fe4da17caryclark// if found, see if the opposite pair can match it -- which may require 163655888e44171ffd48b591d19256884a969fe4da17caryclark// reordering the ptT pairs 163755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* log) const { 163855888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = fHead; 163955888e44171ffd48b591d19256884a969fe4da17caryclark if (!coin) { 164055888e44171ffd48b591d19256884a969fe4da17caryclark return; 164155888e44171ffd48b591d19256884a969fe4da17caryclark } 164255888e44171ffd48b591d19256884a969fe4da17caryclark do { 164355888e44171ffd48b591d19256884a969fe4da17caryclark // most commonly, concidence are one span long; check for that first 164455888e44171ffd48b591d19256884a969fe4da17caryclark int intervals = coin->spanCount(); 164555888e44171ffd48b591d19256884a969fe4da17caryclark if (intervals = 1) { 164655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 164755888e44171ffd48b591d19256884a969fe4da17caryclark // SkASSERT(!coin->debugExpand(nullptr, nullptr)); 164855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 164955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 165055888e44171ffd48b591d19256884a969fe4da17caryclark } 165155888e44171ffd48b591d19256884a969fe4da17caryclark coin->debugExpand(id, log); 165255888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->spanCount() <= 0) { 165355888e44171ffd48b591d19256884a969fe4da17caryclark return; 165426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 165555888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if every span in coin has a mate in opp 165655888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStart()->span()->upCast(); 165755888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 165855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oppStartBase = coin->oppPtTStart()->span(); 165955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* oppStart = flipped ? oppStartBase->prev() : oppStartBase->upCast(); 166055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("", start, oppStart); 166155888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 166255888e44171ffd48b591d19256884a969fe4da17caryclark return; 166326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 166426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 166555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with expand() 166655888e44171ffd48b591d19256884a969fe4da17caryclark// expand the range by checking adjacent spans for coincidence 166726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const { 166826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 166926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 167026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 167126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 167226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 167326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 167455888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->debugExpand(id, log)) { 167555888e44171ffd48b591d19256884a969fe4da17caryclark // check to see if multiple spans expanded so they are now identical 167655888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = fHead; 167755888e44171ffd48b591d19256884a969fe4da17caryclark do { 167855888e44171ffd48b591d19256884a969fe4da17caryclark if (coin == test) { 167955888e44171ffd48b591d19256884a969fe4da17caryclark continue; 168055888e44171ffd48b591d19256884a969fe4da17caryclark } 168155888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == test->coinPtTStart() 168255888e44171ffd48b591d19256884a969fe4da17caryclark && coin->oppPtTStart() == test->oppPtTStart()) { 168355888e44171ffd48b591d19256884a969fe4da17caryclark if (log) log->record(kExpandCoin_Glitch, id, fHead, test->coinPtTStart()); 168455888e44171ffd48b591d19256884a969fe4da17caryclark break; 168555888e44171ffd48b591d19256884a969fe4da17caryclark } 168655888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next())); 168755888e44171ffd48b591d19256884a969fe4da17caryclark expanded = true; 168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168955888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 169026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 169126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 169226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 169355888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with removeCollapsed() 169455888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugRemoveCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log) const { 169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 169626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 169726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 169826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169955888e44171ffd48b591d19256884a969fe4da17caryclark // SkCoincidentSpans** priorPtr = &fHead; 170026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 170155888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart() == coin->coinPtTEnd()) { 170255888e44171ffd48b591d19256884a969fe4da17caryclark return; 170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170455888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->oppPtTStart() == coin->oppPtTEnd()) { 170555888e44171ffd48b591d19256884a969fe4da17caryclark return; 170626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170755888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->coinPtTStart()->collapsed(coin->coinPtTEnd())) { 170855888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 170955888e44171ffd48b591d19256884a969fe4da17caryclark// continue; 171026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171155888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->oppPtTStart()->collapsed(coin->oppPtTEnd())) { 171255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin, coin); 171355888e44171ffd48b591d19256884a969fe4da17caryclark// continue; 171426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 171555888e44171ffd48b591d19256884a969fe4da17caryclark // priorPtr = &coin->nextPtr(); 171655888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 171755888e44171ffd48b591d19256884a969fe4da17caryclark return; 171826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 171926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 172055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mark() 172155888e44171ffd48b591d19256884a969fe4da17caryclark/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 172226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const { 172326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 172426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 172526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 172626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 172726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 172855888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 172955888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(start->deleted()); 173055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 173155888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(end->deleted()); 173255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 173355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oStart->deleted()); 173455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 173555888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oEnd->deleted()); 173655888e44171ffd48b591d19256884a969fe4da17caryclark bool flipped = coin->flipped(); 173726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 173826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 173926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 174055888e44171ffd48b591d19256884a969fe4da17caryclark /* coin and opp spans may not match up. Mark the ends, and then let the interior 174155888e44171ffd48b591d19256884a969fe4da17caryclark get marked as many times as the spans allow */ 174255888e44171ffd48b591d19256884a969fe4da17caryclark start->debugInsertCoincidence(id, log, oStart->upCast()); 174355888e44171ffd48b591d19256884a969fe4da17caryclark end->debugInsertCoinEnd(id, log, oEnd); 174455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* segment = start->segment(); 174555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oSegment = oStart->segment(); 174626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 174726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 174855888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->upCast()->next()) != end) { 174955888e44171ffd48b591d19256884a969fe4da17caryclark if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flipped), false) { 175055888e44171ffd48b591d19256884a969fe4da17caryclark return; 175126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 175255888e44171ffd48b591d19256884a969fe4da17caryclark } 175355888e44171ffd48b591d19256884a969fe4da17caryclark while ((oNext = oNext->upCast()->next()) != oEnd) { 175455888e44171ffd48b591d19256884a969fe4da17caryclark if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flipped), false) { 175555888e44171ffd48b591d19256884a969fe4da17caryclark return; 175626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 175755888e44171ffd48b591d19256884a969fe4da17caryclark } 175855888e44171ffd48b591d19256884a969fe4da17caryclark } while ((coin = coin->next())); 175955888e44171ffd48b591d19256884a969fe4da17caryclark return; 176055888e44171ffd48b591d19256884a969fe4da17caryclark} 176155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 176255888e44171ffd48b591d19256884a969fe4da17caryclark 176355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 176455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 176555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 176655888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 176755888e44171ffd48b591d19256884a969fe4da17caryclark if (coin->collapsed(test)) { 176855888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 176955888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 177026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 177155888e44171ffd48b591d19256884a969fe4da17caryclark if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 177255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kCollapsedCoin_Glitch, id, coin); 177355888e44171ffd48b591d19256884a969fe4da17caryclark } 177455888e44171ffd48b591d19256884a969fe4da17caryclark } 177555888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 177655888e44171ffd48b591d19256884a969fe4da17caryclark } 177755888e44171ffd48b591d19256884a969fe4da17caryclark} 177855888e44171ffd48b591d19256884a969fe4da17caryclark 177955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with markCollapsed() 178055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 178155888e44171ffd48b591d19256884a969fe4da17caryclark this->debugMarkCollapsed(id, log, fHead, test); 178255888e44171ffd48b591d19256884a969fe4da17caryclark this->debugMarkCollapsed(id, log, fTop, test); 178326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 178426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 178526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 178655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkCoincidentSpans::debugShow() const { 178755888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 178855888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->segment()->debugID(), 178955888e44171ffd48b591d19256884a969fe4da17caryclark coinPtTStart()->fT, coinPtTEnd()->fT); 179055888e44171ffd48b591d19256884a969fe4da17caryclark SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 179155888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->segment()->debugID(), 179255888e44171ffd48b591d19256884a969fe4da17caryclark oppPtTStart()->fT, oppPtTEnd()->fT); 179355888e44171ffd48b591d19256884a969fe4da17caryclark} 179455888e44171ffd48b591d19256884a969fe4da17caryclark 1795624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 179655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 179755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* span = fHead; 1798624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 179955888e44171ffd48b591d19256884a969fe4da17caryclark span->debugShow(); 180055888e44171ffd48b591d19256884a969fe4da17caryclark span = span->next(); 1801624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 180255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 1803624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 1804624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 180526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 180655888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end, 180755888e44171ffd48b591d19256884a969fe4da17caryclark double oStart, double oEnd, const SkOpSegment* oSegment, 180855888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 180955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(next != end); 181055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(!next->contains(end) || log); 181155888e44171ffd48b591d19256884a969fe4da17caryclark if (next->t() > end->t()) { 181255888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(next, end); 181355888e44171ffd48b591d19256884a969fe4da17caryclark } 181455888e44171ffd48b591d19256884a969fe4da17caryclark do { 181555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* ptT = next->ptT(); 181655888e44171ffd48b591d19256884a969fe4da17caryclark int index = 0; 181755888e44171ffd48b591d19256884a969fe4da17caryclark bool somethingBetween; 181855888e44171ffd48b591d19256884a969fe4da17caryclark do { 181955888e44171ffd48b591d19256884a969fe4da17caryclark ++index; 182055888e44171ffd48b591d19256884a969fe4da17caryclark ptT = ptT->next(); 182155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* checkPtT = next->ptT(); 182255888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT == checkPtT) { 182355888e44171ffd48b591d19256884a969fe4da17caryclark break; 182455888e44171ffd48b591d19256884a969fe4da17caryclark } 182555888e44171ffd48b591d19256884a969fe4da17caryclark bool looped = false; 182655888e44171ffd48b591d19256884a969fe4da17caryclark for (int check = 0; check < index; ++check) { 182755888e44171ffd48b591d19256884a969fe4da17caryclark if ((looped = checkPtT == ptT)) { 182855888e44171ffd48b591d19256884a969fe4da17caryclark break; 182955888e44171ffd48b591d19256884a969fe4da17caryclark } 183055888e44171ffd48b591d19256884a969fe4da17caryclark checkPtT = checkPtT->next(); 183155888e44171ffd48b591d19256884a969fe4da17caryclark } 183255888e44171ffd48b591d19256884a969fe4da17caryclark if (looped) { 183355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(0); 183455888e44171ffd48b591d19256884a969fe4da17caryclark break; 183555888e44171ffd48b591d19256884a969fe4da17caryclark } 183655888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->deleted()) { 183755888e44171ffd48b591d19256884a969fe4da17caryclark continue; 183855888e44171ffd48b591d19256884a969fe4da17caryclark } 183955888e44171ffd48b591d19256884a969fe4da17caryclark if (ptT->segment() != oSegment) { 184055888e44171ffd48b591d19256884a969fe4da17caryclark continue; 184155888e44171ffd48b591d19256884a969fe4da17caryclark } 184255888e44171ffd48b591d19256884a969fe4da17caryclark somethingBetween |= between(oStart, ptT->fT, oEnd); 184355888e44171ffd48b591d19256884a969fe4da17caryclark } while (true); 184455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(somethingBetween); 184555888e44171ffd48b591d19256884a969fe4da17caryclark } while (next != end && (next = next->upCast()->next())); 184655888e44171ffd48b591d19256884a969fe4da17caryclark} 184755888e44171ffd48b591d19256884a969fe4da17caryclark 184855888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 184955888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 185055888e44171ffd48b591d19256884a969fe4da17caryclark if (!list) { 185155888e44171ffd48b591d19256884a969fe4da17caryclark return; 185255888e44171ffd48b591d19256884a969fe4da17caryclark } 185355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 185455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 185555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 185655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 185755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coinSeg != test->oppPtTStart()->segment()); 185855888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 185955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tcs, 1)); 186055888e44171ffd48b591d19256884a969fe4da17caryclark SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 186155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tce, 1)); 186255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tcs < tce); 186355888e44171ffd48b591d19256884a969fe4da17caryclark double tos = test->oppPtTStart()->fT; 186455888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, tos, 1)); 186555888e44171ffd48b591d19256884a969fe4da17caryclark double toe = test->oppPtTEnd()->fT; 186655888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(between(0, toe, 1)); 186755888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tos != toe); 186855888e44171ffd48b591d19256884a969fe4da17caryclark if (tos > toe) { 186955888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(tos, toe); 187055888e44171ffd48b591d19256884a969fe4da17caryclark } 187155888e44171ffd48b591d19256884a969fe4da17caryclark do { 187255888e44171ffd48b591d19256884a969fe4da17caryclark double lcs, lce, los, loe; 187355888e44171ffd48b591d19256884a969fe4da17caryclark if (coinSeg == list->coinPtTStart()->segment()) { 187455888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->oppPtTStart()->segment()) { 187555888e44171ffd48b591d19256884a969fe4da17caryclark continue; 187655888e44171ffd48b591d19256884a969fe4da17caryclark } 187755888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->coinPtTStart()->fT; 187855888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->coinPtTEnd()->fT; 187955888e44171ffd48b591d19256884a969fe4da17caryclark los = list->oppPtTStart()->fT; 188055888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->oppPtTEnd()->fT; 188155888e44171ffd48b591d19256884a969fe4da17caryclark if (los > loe) { 188255888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(los, loe); 188355888e44171ffd48b591d19256884a969fe4da17caryclark } 188455888e44171ffd48b591d19256884a969fe4da17caryclark } else if (coinSeg == list->oppPtTStart()->segment()) { 188555888e44171ffd48b591d19256884a969fe4da17caryclark if (oppSeg != list->coinPtTStart()->segment()) { 188655888e44171ffd48b591d19256884a969fe4da17caryclark continue; 188755888e44171ffd48b591d19256884a969fe4da17caryclark } 188855888e44171ffd48b591d19256884a969fe4da17caryclark lcs = list->oppPtTStart()->fT; 188955888e44171ffd48b591d19256884a969fe4da17caryclark lce = list->oppPtTEnd()->fT; 189055888e44171ffd48b591d19256884a969fe4da17caryclark if (lcs > lce) { 189155888e44171ffd48b591d19256884a969fe4da17caryclark SkTSwap(lcs, lce); 189255888e44171ffd48b591d19256884a969fe4da17caryclark } 189355888e44171ffd48b591d19256884a969fe4da17caryclark los = list->coinPtTStart()->fT; 189455888e44171ffd48b591d19256884a969fe4da17caryclark loe = list->coinPtTEnd()->fT; 189555888e44171ffd48b591d19256884a969fe4da17caryclark } else { 189655888e44171ffd48b591d19256884a969fe4da17caryclark continue; 189755888e44171ffd48b591d19256884a969fe4da17caryclark } 189855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(tce < lcs || lce < tcs); 189955888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(toe < los || loe < tos); 190055888e44171ffd48b591d19256884a969fe4da17caryclark } while ((list = list->next())); 190155888e44171ffd48b591d19256884a969fe4da17caryclark} 190255888e44171ffd48b591d19256884a969fe4da17caryclark 190355888e44171ffd48b591d19256884a969fe4da17caryclark 190455888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 190555888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 190655888e44171ffd48b591d19256884a969fe4da17caryclark // check for overlapping coincident spans 190755888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* test = head; 190855888e44171ffd48b591d19256884a969fe4da17caryclark while (test) { 190955888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* next = test->next(); 191055888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlap(test, next, id, log); 191155888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlap(test, opt, id, log); 191255888e44171ffd48b591d19256884a969fe4da17caryclark test = next; 191355888e44171ffd48b591d19256884a969fe4da17caryclark } 191455888e44171ffd48b591d19256884a969fe4da17caryclark} 191555888e44171ffd48b591d19256884a969fe4da17caryclark 191655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 191755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLog* log) const { 191855888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(fHead, fTop, id, log); 191955888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(fTop, nullptr, id, log); 192055888e44171ffd48b591d19256884a969fe4da17caryclark} 192155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 192255888e44171ffd48b591d19256884a969fe4da17caryclark 192355888e44171ffd48b591d19256884a969fe4da17caryclarkstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 192455888e44171ffd48b591d19256884a969fe4da17caryclark const char* id, SkPathOpsDebug::GlitchLog* log) { 192555888e44171ffd48b591d19256884a969fe4da17caryclark // look for pts inside coincident spans that are not inside the opposite spans 192655888e44171ffd48b591d19256884a969fe4da17caryclark const SkCoincidentSpans* coin = head; 192755888e44171ffd48b591d19256884a969fe4da17caryclark while (coin) { 192855888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 192955888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->segment())); 193055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 193155888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 193255888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 193355888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 193455888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 193555888e44171ffd48b591d19256884a969fe4da17caryclark coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 193655888e44171ffd48b591d19256884a969fe4da17caryclark id, log); 193755888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 193855888e44171ffd48b591d19256884a969fe4da17caryclark coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 193955888e44171ffd48b591d19256884a969fe4da17caryclark id, log); 194055888e44171ffd48b591d19256884a969fe4da17caryclark coin = coin->next(); 194155888e44171ffd48b591d19256884a969fe4da17caryclark } 194255888e44171ffd48b591d19256884a969fe4da17caryclark DebugCheckOverlapTop(head, opt, id, log); 194355888e44171ffd48b591d19256884a969fe4da17caryclark} 194455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 194555888e44171ffd48b591d19256884a969fe4da17caryclark 194655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugValidate() const { 194755888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 194855888e44171ffd48b591d19256884a969fe4da17caryclark // if (fGlobalState->debugCheckHealth()) { 194955888e44171ffd48b591d19256884a969fe4da17caryclark// return; 195055888e44171ffd48b591d19256884a969fe4da17caryclark// } 195155888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fHead, fTop, nullptr, nullptr); 195255888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fTop, nullptr, nullptr, nullptr); 195355888e44171ffd48b591d19256884a969fe4da17caryclark#endif 195455888e44171ffd48b591d19256884a969fe4da17caryclark} 195555888e44171ffd48b591d19256884a969fe4da17caryclark 195655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 195755888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpCoincidence::debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const { 195855888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fHead, fTop, id, log); 195955888e44171ffd48b591d19256884a969fe4da17caryclark DebugValidate(fTop, nullptr, id, log); 196055888e44171ffd48b591d19256884a969fe4da17caryclark} 196155888e44171ffd48b591d19256884a969fe4da17caryclark#endif 196255888e44171ffd48b591d19256884a969fe4da17caryclark 196355888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 196426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* log) const { 196526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 196626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 196726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark segment->debugCheckHealth(id, log); 196826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((segment = segment->next())); 196926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 197026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 197155888e44171ffd48b591d19256884a969fe4da17caryclark// commmented-out lines keep this aligned with missingCoincidence() 197255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 197355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(fCount > 0); 197426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 197555888e44171ffd48b591d19256884a969fe4da17caryclark// bool result = false; 197626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 197755888e44171ffd48b591d19256884a969fe4da17caryclark if (fState->angleCoincidence()) { 197855888e44171ffd48b591d19256884a969fe4da17caryclark// #if DEBUG_ANGLE 197955888e44171ffd48b591d19256884a969fe4da17caryclark// segment->debugCheckAngleCoin(); 198055888e44171ffd48b591d19256884a969fe4da17caryclark// #endif 198155888e44171ffd48b591d19256884a969fe4da17caryclark } else if (segment->debugMissingCoincidence(id, log), false) { 198255888e44171ffd48b591d19256884a969fe4da17caryclark// result = true; 198355888e44171ffd48b591d19256884a969fe4da17caryclark// see FIXME in missingCoincidence() 198455888e44171ffd48b591d19256884a969fe4da17caryclark// 198555888e44171ffd48b591d19256884a969fe4da17caryclark// 198655888e44171ffd48b591d19256884a969fe4da17caryclark// 198755888e44171ffd48b591d19256884a969fe4da17caryclark // continue; 198855888e44171ffd48b591d19256884a969fe4da17caryclark } 198955888e44171ffd48b591d19256884a969fe4da17caryclark segment = segment->next(); 199055888e44171ffd48b591d19256884a969fe4da17caryclark } while (segment); 199155888e44171ffd48b591d19256884a969fe4da17caryclark return; 199226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 199326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 199426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 19954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 199655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 199755888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 199855888e44171ffd48b591d19256884a969fe4da17caryclark return; 199955888e44171ffd48b591d19256884a969fe4da17caryclark } 200055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 20014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 200254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 200354359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 200496fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 200554359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 20064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 200754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 200854359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 200954359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 201054359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 201154359294a7c9dc54802d512a5d891a35c1663392caryclark } 201254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 201354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 201454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 201554359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 201654359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 201754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 201854359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 201954359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 202054359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 202154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 202254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 202308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 202454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 202554359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 202654359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 202754359294a7c9dc54802d512a5d891a35c1663392caryclark} 202854359294a7c9dc54802d512a5d891a35c1663392caryclark 202955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 203055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOppAndMerge() 203155888e44171ffd48b591d19256884a969fe4da17caryclark// If the added points envelop adjacent spans, merge them in. 203255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const { 203355888e44171ffd48b591d19256884a969fe4da17caryclark if (this->ptT()->debugAddOpp(opp->ptT())) { 203455888e44171ffd48b591d19256884a969fe4da17caryclark this->debugCheckForCollapsedCoincidence(id, log); 203526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 203655888e44171ffd48b591d19256884a969fe4da17caryclark // compute bounds of points in span 203755888e44171ffd48b591d19256884a969fe4da17caryclark SkPathOpsBounds bounds; 203855888e44171ffd48b591d19256884a969fe4da17caryclark bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin); 203955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 204055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* nextPt = head; 204155888e44171ffd48b591d19256884a969fe4da17caryclark do { 204255888e44171ffd48b591d19256884a969fe4da17caryclark bounds.add(nextPt->fPt); 204355888e44171ffd48b591d19256884a969fe4da17caryclark } while ((nextPt = nextPt->next()) != head); 204455888e44171ffd48b591d19256884a969fe4da17caryclark if (!bounds.width() && !bounds.height()) { 204555888e44171ffd48b591d19256884a969fe4da17caryclark return; 204626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 204755888e44171ffd48b591d19256884a969fe4da17caryclark this->debugMergeContained(id, log, bounds, spanDeleted); 204855888e44171ffd48b591d19256884a969fe4da17caryclark opp->debugMergeContained(id, log, bounds, oppDeleted); 204926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 205026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 205155888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 205255888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log) const { 205355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpCoincidence* coins = this->globalState()->coincidence(); 205455888e44171ffd48b591d19256884a969fe4da17caryclark if (coins->isEmpty()) { 205555888e44171ffd48b591d19256884a969fe4da17caryclark return; 205655888e44171ffd48b591d19256884a969fe4da17caryclark } 205755888e44171ffd48b591d19256884a969fe4da17caryclark// the insert above may have put both ends of a coincident run in the same span 205855888e44171ffd48b591d19256884a969fe4da17caryclark// for each coincident ptT in loop; see if its opposite in is also in the loop 205955888e44171ffd48b591d19256884a969fe4da17caryclark// this implementation is the motivation for marking that a ptT is referenced by a coincident span 206055888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* head = this->ptT(); 206155888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* test = head; 206226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 206355888e44171ffd48b591d19256884a969fe4da17caryclark if (!test->coincident()) { 206455888e44171ffd48b591d19256884a969fe4da17caryclark continue; 206526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 206655888e44171ffd48b591d19256884a969fe4da17caryclark coins->debugMarkCollapsed(id, log, test); 206755888e44171ffd48b591d19256884a969fe4da17caryclark } while ((test = test->next()) != head); 206826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 206955888e44171ffd48b591d19256884a969fe4da17caryclark#endif 207026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 207154359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 207254359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 207354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 207454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 207554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 207654359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 207754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 207854359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 207954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 208054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 208154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 208254359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 208354359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 208454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 208554359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 208654359294a7c9dc54802d512a5d891a35c1663392caryclark } 208754359294a7c9dc54802d512a5d891a35c1663392caryclark } 208854359294a7c9dc54802d512a5d891a35c1663392caryclark } 208954359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 209054359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 209154359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 209254359294a7c9dc54802d512a5d891a35c1663392caryclark} 209354359294a7c9dc54802d512a5d891a35c1663392caryclark 209455888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 209555888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoinEnd() 209655888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugInsertCoinEnd(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 209755888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoinEnd(coin)) { 209855888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoinEnd(this)); 209955888e44171ffd48b591d19256884a969fe4da17caryclark return; 210055888e44171ffd48b591d19256884a969fe4da17caryclark } 210155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 210255888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 210355888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinEnd_Glitch, id, this, coin); 210455888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoinEnd = this->fCoinEnd; 210555888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoinEnd = coinNext; 210655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 210755888e44171ffd48b591d19256884a969fe4da17caryclark} 210855888e44171ffd48b591d19256884a969fe4da17caryclark 210955888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with mergeContained() 211055888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog* log, const SkPathOpsBounds& bounds, bool* deleted) const { 211155888e44171ffd48b591d19256884a969fe4da17caryclark // while adjacent spans' points are contained by the bounds, merge them 211255888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* prev = this; 211355888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSegment* seg = this->segment(); 211455888e44171ffd48b591d19256884a969fe4da17caryclark while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisjoint(prev, this)) { 211555888e44171ffd48b591d19256884a969fe4da17caryclark if (prev->prev()) { 211655888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, this, prev); 211755888e44171ffd48b591d19256884a969fe4da17caryclark } else if (this->final()) { 211855888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, this, prev); 211955888e44171ffd48b591d19256884a969fe4da17caryclark // return; 212055888e44171ffd48b591d19256884a969fe4da17caryclark } else { 212155888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, prev, this); 212226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 212326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 212455888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* current = this; 212555888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpSpanBase* next = this; 212655888e44171ffd48b591d19256884a969fe4da17caryclark while (next->upCastable() && (next = next->upCast()->next()) 212755888e44171ffd48b591d19256884a969fe4da17caryclark && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) { 212855888e44171ffd48b591d19256884a969fe4da17caryclark if (!current->prev() && next->final()) { 212955888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 213055888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 213155888e44171ffd48b591d19256884a969fe4da17caryclark } 213255888e44171ffd48b591d19256884a969fe4da17caryclark if (current->prev()) { 213355888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 213455888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 213555888e44171ffd48b591d19256884a969fe4da17caryclark } else { 213655888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMergeContained_Glitch, id, next, current); 213755888e44171ffd48b591d19256884a969fe4da17caryclark current = next; 213855888e44171ffd48b591d19256884a969fe4da17caryclark } 213955888e44171ffd48b591d19256884a969fe4da17caryclark } 214055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 214155888e44171ffd48b591d19256884a969fe4da17caryclark // this->globalState()->coincidence()->debugValidate(); 214255888e44171ffd48b591d19256884a969fe4da17caryclark#endif 214326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 214455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 214526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 214626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 214726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 214826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 214926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 215026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 215126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 215226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 215326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 215426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 215526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 215626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 215726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 215826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 215954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 216055888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 216155888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 216255888e44171ffd48b591d19256884a969fe4da17caryclark return; 216355888e44171ffd48b591d19256884a969fe4da17caryclark } 216455888e44171ffd48b591d19256884a969fe4da17caryclark#endif 216554359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 216654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 216754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 216854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 216954359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 217054359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 217154359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 217254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 217354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 217454359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 217554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 217654359294a7c9dc54802d512a5d891a35c1663392caryclark } 217754359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 217854359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 217954359294a7c9dc54802d512a5d891a35c1663392caryclark } 218054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 218154359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 218254359294a7c9dc54802d512a5d891a35c1663392caryclark } 21834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 218454359294a7c9dc54802d512a5d891a35c1663392caryclark} 218554359294a7c9dc54802d512a5d891a35c1663392caryclark 218654359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 218754359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 218854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 218954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 219054359294a7c9dc54802d512a5d891a35c1663392caryclark do { 219154359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 219254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 219354359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 219454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 219554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 219654359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 219754359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 219854359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 219954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 220054359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 220154359294a7c9dc54802d512a5d891a35c1663392caryclark } 220254359294a7c9dc54802d512a5d891a35c1663392caryclark } 220354359294a7c9dc54802d512a5d891a35c1663392caryclark } 220454359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 220554359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 220654359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 220754359294a7c9dc54802d512a5d891a35c1663392caryclark} 220854359294a7c9dc54802d512a5d891a35c1663392caryclark 220955888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE_VERBOSE 221055888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() in header 221155888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 221255888e44171ffd48b591d19256884a969fe4da17caryclark if (containsCoincidence(coin)) { 221355888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(coin->containsCoincidence(this)); 221455888e44171ffd48b591d19256884a969fe4da17caryclark return; 221555888e44171ffd48b591d19256884a969fe4da17caryclark } 221655888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 221755888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(this != coin); 221855888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinStart_Glitch, id, this, coin); 221955888e44171ffd48b591d19256884a969fe4da17caryclark// coin->fCoincident = this->fCoincident; 222055888e44171ffd48b591d19256884a969fe4da17caryclark// this->fCoincident = coinNext; 222155888e44171ffd48b591d19256884a969fe4da17caryclark debugValidate(); 222255888e44171ffd48b591d19256884a969fe4da17caryclark} 222355888e44171ffd48b591d19256884a969fe4da17caryclark 222455888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with insertCoincidence() 222555888e44171ffd48b591d19256884a969fe4da17caryclarkvoid SkOpSpan::debugInsertCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped) const { 222655888e44171ffd48b591d19256884a969fe4da17caryclark if (this->containsCoincidence(segment)) { 222755888e44171ffd48b591d19256884a969fe4da17caryclark return; 222855888e44171ffd48b591d19256884a969fe4da17caryclark } 222955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* next = &fPtT; 223055888e44171ffd48b591d19256884a969fe4da17caryclark while ((next = next->next()) != &fPtT) { 223155888e44171ffd48b591d19256884a969fe4da17caryclark if (next->segment() == segment) { 223255888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinInsert_Glitch, id, flipped ? next->span()->prev() : next->span()); 223355888e44171ffd48b591d19256884a969fe4da17caryclark return; 223455888e44171ffd48b591d19256884a969fe4da17caryclark } 223555888e44171ffd48b591d19256884a969fe4da17caryclark } 223655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 223755888e44171ffd48b591d19256884a969fe4da17caryclark log->record(kMarkCoinMissing_Glitch, id, segment, this); 223855888e44171ffd48b591d19256884a969fe4da17caryclark#endif 223955888e44171ffd48b591d19256884a969fe4da17caryclark} 224055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 224155888e44171ffd48b591d19256884a969fe4da17caryclark 2242624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 2243624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 2244624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 2245624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 2246624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 2247624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2248624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 2249624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 2250624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 2251624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 2252624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 2253624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2254624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 2255624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 2256624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 2257624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2258624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 2259624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 2260624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 2261624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 2262624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 2263624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 226454359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 226554359294a7c9dc54802d512a5d891a35c1663392caryclark 226655888e44171ffd48b591d19256884a969fe4da17caryclark// Commented-out lines keep this in sync with addOpp() 226755888e44171ffd48b591d19256884a969fe4da17caryclarkbool SkOpPtT::debugAddOpp(const SkOpPtT* opp) const { 226855888e44171ffd48b591d19256884a969fe4da17caryclark // find the fOpp ptr to opp 226955888e44171ffd48b591d19256884a969fe4da17caryclark const SkOpPtT* oppPrev = opp->fNext; 227055888e44171ffd48b591d19256884a969fe4da17caryclark if (oppPrev == this) { 227155888e44171ffd48b591d19256884a969fe4da17caryclark return false; 227255888e44171ffd48b591d19256884a969fe4da17caryclark } 227355888e44171ffd48b591d19256884a969fe4da17caryclark while (oppPrev->fNext != opp) { 227455888e44171ffd48b591d19256884a969fe4da17caryclark oppPrev = oppPrev->fNext; 227555888e44171ffd48b591d19256884a969fe4da17caryclark if (oppPrev == this) { 227655888e44171ffd48b591d19256884a969fe4da17caryclark return false; 227755888e44171ffd48b591d19256884a969fe4da17caryclark } 227855888e44171ffd48b591d19256884a969fe4da17caryclark } 227955888e44171ffd48b591d19256884a969fe4da17caryclark// const SkOpPtT* oldNext = this->fNext; 228055888e44171ffd48b591d19256884a969fe4da17caryclark SkASSERT(this != opp); 228155888e44171ffd48b591d19256884a969fe4da17caryclark// this->fNext = opp; 228255888e44171ffd48b591d19256884a969fe4da17caryclark// SkASSERT(oppPrev != oldNext); 228355888e44171ffd48b591d19256884a969fe4da17caryclark// oppPrev->fNext = oldNext; 228455888e44171ffd48b591d19256884a969fe4da17caryclark return true; 228555888e44171ffd48b591d19256884a969fe4da17caryclark} 228655888e44171ffd48b591d19256884a969fe4da17caryclark 228726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 228826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 228926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 229026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 229126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 229226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 229326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 229426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 229526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 229626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 229726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 229826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 229926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 230026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 230126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 230226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 230326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 230426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 230526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 230626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 230726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 230826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 230926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 231026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 231126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 231226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 231326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 231426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 231526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 231626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 231726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 231826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 231926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 232026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 232126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 232226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 232326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 232426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 232526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 232626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 232754359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 232854359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 232954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 233054359294a7c9dc54802d512a5d891a35c1663392caryclark do { 233154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 233254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 233354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 233454359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 233554359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 233654359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 233754359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 233854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 233954359294a7c9dc54802d512a5d891a35c1663392caryclark } 234054359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 234154359294a7c9dc54802d512a5d891a35c1663392caryclark } 23424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 234426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 234526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 234626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 234726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 234826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 234926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 235026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 235154359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 235254359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 235354359294a7c9dc54802d512a5d891a35c1663392caryclark} 235454359294a7c9dc54802d512a5d891a35c1663392caryclark 235554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 235655888e44171ffd48b591d19256884a969fe4da17caryclark#if DEBUG_COINCIDENCE 235755888e44171ffd48b591d19256884a969fe4da17caryclark if (this->globalState()->debugCheckHealth()) { 235855888e44171ffd48b591d19256884a969fe4da17caryclark return; 235955888e44171ffd48b591d19256884a969fe4da17caryclark } 236055888e44171ffd48b591d19256884a969fe4da17caryclark#endif 236154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 23624e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark SkOpGlobalState::Phase phase = contour()->globalState()->phase(); 23634e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark if (phase == SkOpGlobalState::kIntersecting 23644e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark || phase == SkOpGlobalState::kFixWinding) { 236554359294a7c9dc54802d512a5d891a35c1663392caryclark return; 23664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 236754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 236854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 236954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 237054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 23714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 23724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 23731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 23741049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 23751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 23761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 23771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 23781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 23791049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 23801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 23811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 23821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 23831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 23841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 23851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 23861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 23871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 23881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 23891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 23901049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 23911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 23921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 23931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 23941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 23951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 23961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 23971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 23981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 23991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 24001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 24011049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 24021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 24031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 24041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 24051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 24061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 24071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 24081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 24091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 24101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 24111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 24121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 24131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 24141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 24151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 24161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 24171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 24181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 24191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 24201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 24211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 24221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 24231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 24241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 24251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 24261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 24271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 24281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 24291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 24301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 24311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 24321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 24331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 24341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 24351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 24361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 24371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 24381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 24391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 24401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 24411049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 24421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 24431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 24441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 24451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 24461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 24471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 24481049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 24491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 24501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 24511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 245296fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 24531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 24541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 24551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 24561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 24571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 24581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 24591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 24601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 24611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 24621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 24631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 24641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 24651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 24661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 24671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 24681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 24691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 24701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 24711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 24721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 24731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 24741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 24751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 24761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 2477