1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2013 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMutex.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpCoincidence.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpContour.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSFile.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsDebug.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_DUMP_VERIFY 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::gDumpOp; // set to true to write op to file before a crash 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::gVerifyOp; // set to true to compare result against regions 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::gRunFail; // set to true to check for success on tests known to fail 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::gVeryVerbose; // set to true to run extensive checking tests 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef FAIL_IF 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define FAIL_IF(cond, coin) \ 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false) 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef FAIL_WITH_NULL_IF 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define FAIL_WITH_NULL_IF(cond, span) \ 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, span); } while (false) 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef RETURN_FALSE_IF 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define RETURN_FALSE_IF(cond, span) \ 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { if (cond) log->record(SkPathOpsDebug::kReturnFalse_Glitch, span); \ 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (false) 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkCoincidentSpans; 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SORT 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkPathOpsDebug::gSortCount; 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ACTIVE_OP 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor", "rdiff"}; 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined SK_DEBUG || !FORCE_RELEASE 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkPathOpsDebug::gContourID = 0; 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkPathOpsDebug::gSegmentID = 0; 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < chaseArray.count(); ++index) { 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* entry = chaseArray[index]; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (entry == span) { 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ACTIVE_SPANS 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString SkPathOpsDebug::gActiveSpans; 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumChangedDict; 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkPathOpsDebug::CoinDict SkPathOpsDebug::gCoinSumVisitedDict; 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const int kGlitchType_Count = SkPathOpsDebug::kUnalignedTail_Glitch + 1; 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SpanGlitch { 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* fBase; 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* fSuspect; 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* fSegment; 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* fOppSegment; 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* fCoinSpan; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* fEndSpan; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* fOppSpan; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* fOppEndSpan; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double fStartT; 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double fEndT; 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double fOppStartT; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double fOppEndT; 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint fPt; 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchType fType; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void dumpType() const; 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SkPathOpsDebug::GlitchLog { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void init(const SkOpGlobalState* state) { 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fGlobalState = state; 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* recordCommon(GlitchType type) { 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = fGlitches.push(); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = nullptr; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSuspect = nullptr; 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSegment = nullptr; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSegment = nullptr; 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = nullptr; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = nullptr; 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSpan = nullptr; 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndSpan = nullptr; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fStartT = SK_ScalarNaN; 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndT = SK_ScalarNaN; 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppStartT = SK_ScalarNaN; 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndT = SK_ScalarNaN; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fType = type; 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return glitch; 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSpanBase* base, 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* suspect = NULL) { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = base; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSuspect = suspect; 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSpanBase* base, 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT) { 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = base; 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = ptT; 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkCoincidentSpans* coin, 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* opp = NULL) { 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = coin->coinPtTStart(); 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = coin->coinPtTEnd(); 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (opp) { 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSpan = opp->coinPtTStart(); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndSpan = opp->coinPtTEnd(); 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSpanBase* base, 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* seg, double t, SkPoint pt) { 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = base; 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSegment = seg; 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fStartT = t; 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fPt = pt; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSpanBase* base, double t, 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint pt) { 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = base; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fStartT = t; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fPt = pt; 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkCoincidentSpans* coin, 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = coin->coinPtTStart(); 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = coin->coinPtTEnd(); 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = endSpan; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSpan = coinSpan; 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndSpan = endSpan; 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkCoincidentSpans* coin, 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* base) { 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = base; 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = coin->coinPtTStart(); 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = coin->coinPtTEnd(); 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = ptTS; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = ptTE; 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSpan = oPtTS; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndSpan = oPtTE; 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSegment* seg, double startT, 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double endT, const SkOpSegment* oppSeg, double oppStartT, double oppEndT) { 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSegment = seg; 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fStartT = startT; 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndT = endT; 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppSegment = oppSeg; 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppStartT = oppStartT; 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fOppEndT = oppEndT; 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSegment* seg, 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span) { 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSegment = seg; 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = span; 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, double t, const SkOpSpanBase* span) { 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fStartT = t; 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fBase = span; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkOpSegment* seg) { 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fSegment = seg; 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void record(GlitchType type, const SkCoincidentSpans* coin, 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT) { 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SpanGlitch* glitch = recordCommon(type); 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fCoinSpan = coin->coinPtTStart(); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch->fEndSpan = ptT; 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SpanGlitch> fGlitches; 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpGlobalState* fGlobalState; 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::CoinDict::add(const SkPathOpsDebug::CoinDict& dict) { 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = dict.fDict.count(); 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < count; ++index) { 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->add(dict.fDict[index]); 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::CoinDict::add(const CoinDictEntry& key) { 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = fDict.count(); 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < count; ++index) { 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot CoinDictEntry* entry = &fDict[index]; 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (entry->fIteration == key.fIteration && entry->fLineNumber == key.fLineNumber) { 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!strcmp(entry->fFunctionName, key.fFunctionName)); 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (entry->fGlitchType == kUninitialized_Glitch) { 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fGlitchType = key.fGlitchType; 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *fDict.append() = key; 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void missing_coincidence(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpContour* contour = contourList; 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // bool result = false; 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* result |= */ contour->debugMissingCoincidence(glitches); 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((contour = contour->next())); 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void move_multiples(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpContour* contour = contourList; 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (contour->debugMoveMultiples(glitches), false) { 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((contour = contour->next())); 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void move_nearby(SkPathOpsDebug::GlitchLog* glitches, const SkOpContourHead* contourList) { 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpContour* contour = contourList; 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contour->debugMoveNearby(glitches); 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((contour = contour->next())); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugAddToCoinChangedDict() { 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::CheckHealth(fContourHead); 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // see if next coincident operation makes a change; if so, record it 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog glitches; 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* funcName = fCoinDictEntry.fFunctionName; 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!strcmp("calc_angles", funcName)) { 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("missing_coincidence", funcName)) { 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot missing_coincidence(&glitches, fContourHead); 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("move_multiples", funcName)) { 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot move_multiples(&glitches, fContourHead); 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("move_nearby", funcName)) { 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot move_nearby(&glitches, fContourHead); 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("addExpanded", funcName)) { 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugAddExpanded(&glitches); 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("addMissing", funcName)) { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool added; 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugAddMissing(&glitches, &added); 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("addEndMovedSpans", funcName)) { 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugAddEndMovedSpans(&glitches); 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("correctEnds", funcName)) { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugCorrectEnds(&glitches); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("expand", funcName)) { 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugExpand(&glitches); 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("findOverlaps", funcName)) { 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("mark", funcName)) { 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoincidence->debugMark(&glitches); 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (!strcmp("apply", funcName)) { 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); // add missing case 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitches.fGlitches.count()) { 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoinDictEntry.fGlitchType = glitches.fGlitches[0].fType; 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCoinChangedDict.add(fCoinDictEntry); 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::ShowActiveSpans(SkOpContourHead* contourList) { 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ACTIVE_SPANS 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString str; 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpContour* contour = contourList; 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contour->debugShowActiveSpans(&str); 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((contour = contour->next())); 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!gActiveSpans.equals(str)) { 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* s = str.c_str(); 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* end; 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((end = strchr(s, '\n'))) { 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%.*s", end - s + 1, s); 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot s = end + 1; 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gActiveSpans.set(str); 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE || DEBUG_COIN 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList) { 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contourList->globalState()->debugSetCheckHealth(true); 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GlitchLog glitches; 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpContour* contour = contourList; 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->debugCheckValid(&glitches); // don't call validate; spans may be inconsistent 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contour->debugCheckHealth(&glitches); 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contour->debugMissingCoincidence(&glitches); 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((contour = contour->next())); 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool added; 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->debugAddMissing(&glitches, &added); 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->debugExpand(&glitches); 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->debugAddExpanded(&glitches); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincidence->debugMark(&glitches); 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned mask = 0; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < glitches.fGlitches.count(); ++index) { 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SpanGlitch& glitch = glitches.fGlitches[index]; 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask |= 1 << glitch.fType; 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < kGlitchType_Count; ++index) { 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(mask & (1 << index) ? "x" : "-"); 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s\n", contourList->globalState()->debugCoinDictEntry().fFunctionName); 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < glitches.fGlitches.count(); ++index) { 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SpanGlitch& glitch = glitches.fGlitches[index]; 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%02d: ", index); 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fBase) { 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(), 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch.fBase->debugID()); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fSuspect) { 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(), 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch.fSuspect->debugID()); 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fSegment) { 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" segment=%d", glitch.fSegment->debugID()); 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fCoinSpan) { 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(), 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID()); 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fEndSpan) { 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID()); 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fOppSpan) { 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(), 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID()); 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fOppEndSpan) { 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID()); 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkScalarIsNaN(glitch.fStartT)) { 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" startT=%g", glitch.fStartT); 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkScalarIsNaN(glitch.fEndT)) { 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" endT=%g", glitch.fEndT); 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glitch.fOppSegment) { 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" segment=%d", glitch.fOppSegment->debugID()); 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkScalarIsNaN(glitch.fOppStartT)) { 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" oppStartT=%g", glitch.fOppStartT); 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkScalarIsNaN(glitch.fOppEndT)) { 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" oppEndT=%g", glitch.fOppEndT); 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkScalarIsNaN(glitch.fPt.fX) || !SkScalarIsNaN(glitch.fPt.fY)) { 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" pt=%g,%g", glitch.fPt.fX, glitch.fPt.fY); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpGlitchType(glitch.fType); 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\n"); 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot contourList->globalState()->debugSetCheckHealth(false); 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 01 && DEBUG_ACTIVE_SPANS 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("active after %s:\n", id); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ShowActiveSpans(contourList); 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DumpGlitchType(GlitchType glitchType) { 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (glitchType) { 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break; 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break; 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break; 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break; 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break; 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break; 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break; 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAddOrOverlap_Glitch: SkDebugf(" AAddOrOverlap"); break; 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCollapsedCoin_Glitch: SkDebugf(" CollapsedCoin"); break; 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCollapsedDone_Glitch: SkDebugf(" CollapsedDone"); break; 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCollapsedOppValue_Glitch: SkDebugf(" CollapsedOppValue"); break; 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCollapsedSpan_Glitch: SkDebugf(" CollapsedSpan"); break; 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCollapsedWindValue_Glitch: SkDebugf(" CollapsedWindValue"); break; 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kCorrectEnd_Glitch: SkDebugf(" CorrectEnd"); break; 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kDeletedCoin_Glitch: SkDebugf(" DeletedCoin"); break; 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kExpandCoin_Glitch: SkDebugf(" ExpandCoin"); break; 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kFail_Glitch: SkDebugf(" Fail"); break; 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMarkCoinEnd_Glitch: SkDebugf(" MarkCoinEnd"); break; 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMarkCoinInsert_Glitch: SkDebugf(" MarkCoinInsert"); break; 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break; 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break; 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break; 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break; 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMissingDone_Glitch: SkDebugf(" MissingDone"); break; 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break; 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveMultiple_Glitch: SkDebugf(" MoveMultiple"); break; 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyClearAll_Glitch: SkDebugf(" MoveNearbyClearAll"); break; 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyClearAll2_Glitch: SkDebugf(" MoveNearbyClearAll2"); break; 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyMerge_Glitch: SkDebugf(" MoveNearbyMerge"); break; 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyMergeFinal_Glitch: SkDebugf(" MoveNearbyMergeFinal"); break; 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyRelease_Glitch: SkDebugf(" MoveNearbyRelease"); break; 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kMoveNearbyReleaseFinal_Glitch: SkDebugf(" MoveNearbyReleaseFinal"); break; 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kReleasedSpan_Glitch: SkDebugf(" ReleasedSpan"); break; 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kReturnFalse_Glitch: SkDebugf(" ReturnFalse"); break; 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kUnaligned_Glitch: SkDebugf(" Unaligned"); break; 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kUnalignedHead_Glitch: SkDebugf(" UnalignedHead"); break; 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kUnalignedTail_Glitch: SkDebugf(" UnalignedTail"); break; 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kUninitialized_Glitch: break; 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: SkASSERT(0); 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined SK_DEBUG || !FORCE_RELEASE 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t len = strlen(str); 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool num = false; 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t idx = 0; idx < len; ++idx) { 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (num && str[idx] == 'e') { 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (len + 2 >= bufferLen) { 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memmove(&str[idx + 2], &str[idx + 1], len - idx); 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str[idx] = '*'; 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str[idx + 1] = '^'; 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++len; 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot num = str[idx] >= '0' && str[idx] <= '9'; 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkPathOpsDebug::ValidWind(int wind) { 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::WindingPrintf(int wind) { 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (wind == SK_MinS32) { 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", wind); 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif // defined SK_DEBUG || !FORCE_RELEASE 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::BumpTestName(char* test) { 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char* num = test + strlen(test); 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (num[-1] >= '0' && num[-1] <= '9') { 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --num; 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (num[0] == '\0') { 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int dec = atoi(num); 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dec == 0) { 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++dec; 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void show_function_header(const char* functionName) { 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (strcmp("skphealth_com76", functionName) == 0) { 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("found it\n"); 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* gOpStrs[] = { 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kDifference_SkPathOp", 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kIntersect_SkPathOp", 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kUnion_SkPathOp", 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kXOR_PathOp", 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kReverseDifference_SkPathOp", 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return gOpStrs[op]; 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("}\n"); 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gTestMutex); 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* testName) { 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gTestMutex); 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot show_function_header(testName); 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ShowOnePath(a, "path", true); 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ShowOnePath(b, "pathB", true); 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot show_op(shapeOp, "path", "pathB"); 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsTypes.h" 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkIntersectionHelper.h" 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkIntersections.h" 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gCoinDictMutex); 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugAddToGlobalCoinDicts() { 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(&gCoinDictMutex); 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict); 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict); 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_T_SECT_LOOP_COUNT 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIntersectionHelper& wn) { 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLoopCount[index] = i->debugLoopCount(looper); 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstVerb[index * 2] = wt.segment()->verb(); 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2] = wt.weight(); 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2 + 1] = wn.weight(); 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot i->debugResetLoopCount(); 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLoopCount[index] = local->fDebugLoopCount[index]; 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sizeof(SkPoint) * 8); 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot local->debugResetLoopCounts(); 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!verb) { 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s: {{", verbs[verb]); 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int ptCount = SkPathOpsVerbToPoints(verb); 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index <= ptCount; ++index) { 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint::Dump((&pts)[index]); 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (index < ptCount - 1) { 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(", "); 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("}"); 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (weight != 1) { 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(", "); 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (weight == floorf(weight)) { 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%.0f", weight); 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%1.9gf", weight); 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("}\n"); 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugLoopReport() { 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\n"); 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2]); 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugWorstWeight[index * 2 + 1]); 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugResetLoopCounts() { 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpGlobalState::DebugRunFail() { 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkPathOpsDebug::gRunFail; 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this is const so it can be called by const methods that overwise don't alter state 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE || DEBUG_COIN 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpGlobalState::debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const { 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto writable = const_cast<SkOpGlobalState*>(this); 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writable->setPhase(phase); 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::CoinDictEntry* entry = &writable->fCoinDictEntry; 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writable->fPreviousFuncName = entry->fFunctionName; 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fIteration = iteration; 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fLineNumber = lineNo; 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fGlitchType = SkPathOpsDebug::kUninitialized_Glitch; 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot entry->fFunctionName = funcName; 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writable->fCoinVisitedDict.add(*entry); 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writable->debugAddToCoinChangedDict(); 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_T_SECT_LOOP_COUNT 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLoopCount[index]++; 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkIntersections::debugLoopCount(DebugLoop index) const { 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fDebugLoopCount[index]; 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkIntersections::debugResetLoopCount() { 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsConic.h" 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsCubic.h" 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkDCubic SkDQuad::debugToCubic() const { 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDCubic cubic; 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[0] = fPts[0]; 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[2] = fPts[1]; 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[3] = fPts[2]; 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return cubic; 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDQuad::debugSet(const SkDPoint* pts) { 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(fPts, pts, sizeof(fPts)); 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fDebugGlobalState = nullptr); 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDCubic::debugSet(const SkDPoint* pts) { 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(fPts, pts, sizeof(fPts)); 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(fDebugGlobalState = nullptr); 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDConic::debugSet(const SkDPoint* pts, SkScalar weight) { 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPts.debugSet(pts); 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWeight = weight; 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDRect::debugInit() { 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpAngle.h" 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpSegment.h" 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with addT() 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* SkOpSegment::debugAddT(double t, SkPathOpsDebug::GlitchLog* log) const { 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint pt = this->ptAtT(t); 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span = &fHead; 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* result = span->ptT(); 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (t == result->fT || this->match(result, this, t, pt)) { 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// span->bumpSpanAdds(); 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (t < result->fT) { 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = result->span()->prev(); 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_WITH_NULL_IF(!prev, span); 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // marks in global state that new op span has been allocated 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->globalState()->setAllocatedOpSpan(); 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// span->init(this, prev, t, pt); 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// #if DEBUG_ADD_T 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// span->segment()->debugID(), span->debugID()); 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// #endif 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// span->bumpSpanAdds(); 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_WITH_NULL_IF(span != &fTail, span); 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->upCast()->next())); 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; // we never get here, but need this to satisfy compiler 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ANGLE 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugCheckAngleCoin() const { 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* base = &fHead; 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span; 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* angle = base->fromAngle(); 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (angle && angle->debugCheckCoincidence()) { 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot angle->debugCheckNearCoincidence(); 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (base->final()) { 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = base->upCast(); 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot angle = span->toAngle(); 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (angle && angle->debugCheckCoincidence()) { 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot angle->debugCheckNearCoincidence(); 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((base = span->next())); 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this mimics the order of the checks in handle coincidence 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugCheckHealth(SkPathOpsDebug::GlitchLog* glitches) const { 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugMoveMultiples(glitches); 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugMoveNearby(glitches); 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugMissingCoincidence(glitches); 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with clearAll() 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugClearAll(SkPathOpsDebug::GlitchLog* glitches) const { 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span = &fHead; 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugClearOne(span, glitches); 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->next()->upCastable())); 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->globalState()->coincidence()->debugRelease(glitches, this); 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with clearOne() 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugClearOne(const SkOpSpan* span, SkPathOpsDebug::GlitchLog* glitches) const { 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->windValue()) glitches->record(SkPathOpsDebug::kCollapsedWindValue_Glitch, span); 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->oppValue()) glitches->record(SkPathOpsDebug::kCollapsedOppValue_Glitch, span); 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!span->done()) glitches->record(SkPathOpsDebug::kCollapsedDone_Glitch, span); 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkOpAngle* SkOpSegment::debugLastAngle() { 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpAngle* result = nullptr; 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* span = this->head(); 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->toAngle()) { 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!result); 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = span->toAngle(); 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->next()->upCastable())); 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(result); 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with ClearVisited 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::DebugClearVisited(const SkOpSpanBase* span) { 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // reset visited flag back to false 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != stopPtT) { 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* opp = ptT->segment(); 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opp->resetDebugVisited(); 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!span->final() && (span = span->upCast()->next())); 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with missingCoincidence() 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// look for pairs of undetected coincident curves 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// assumes that segments going in have visited flag clear 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Even though pairs of curves correct detect coincident runs, a run may be missed 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if the coincidence is a product of multiple intersections. For instance, given 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// curves A, B, and C: 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// A-B intersect at a point 1; A-C and B-C intersect at point 2, so near 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the end of C that the intersection is replaced with the end of C. 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Even though A-B correctly do not detect an intersection at point 2, 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the resulting run from point 1 to point 2 is coincident on A and B. 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->done()) { 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prior = nullptr; 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* spanBase = &fHead; 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// bool result = false; 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(ptT->span() == spanBase); 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != spanStopPtT) { 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->deleted()) { 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* opp = ptT->span()->segment(); 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (opp->done()) { 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!opp->debugVisited()) { 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (spanBase == &fHead) { 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() == this) { 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span = spanBase->upCastable(); 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FIXME?: this assumes that if the opposite segment is coincident then no more 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // coincidence needs to be detected. This may not be true. 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span && span->segment() != opp && span->containsCoincidence(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { // debug has additional condition since it may be called before inner duplicate points have been deleted 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // find prior span containing opp segment 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* priorOpp = nullptr; 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* priorTest = spanBase->prev(); 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (!priorOpp && priorTest) { 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorStopPtT = priorPtT = priorTest->ptT(); 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((priorPtT = priorPtT->next()) != priorStopPtT) { 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (priorPtT->deleted()) { 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = priorPtT->span()->segment(); 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment == opp) { 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prior = priorTest; 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorOpp = opp; 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorTest = priorTest->prev(); 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!priorOpp) { 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (priorPtT == ptT) { 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppStart = prior->ptT(); 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppEnd = spanBase->ptT(); 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool swapped = priorPtT->fT > ptT->fT; 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (swapped) { 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(priorPtT, ptT); 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppStart, oppEnd); 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpCoincidence* coincidence = this->globalState()->coincidence(); 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* rootPriorPtT = priorPtT->span()->ptT(); 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* rootPtT = ptT->span()->ptT(); 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* rootOppStart = oppStart->span()->ptT(); 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* rootOppEnd = oppEnd->span()->ptT(); 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coincidence->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd)) { 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto swapBack; 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) { 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // mark coincidence 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_VERBOSE 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__, 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(), 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// rootOppEnd->debugID()); 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMissingCoin_Glitch, priorPtT, ptT, oppStart, oppEnd); 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // coincidences->add(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // } 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(coincidences->contains(rootPriorPtT, rootPtT, rootOppStart, rootOppEnd); 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // result = true; 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot swapBack: 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (swapped) { 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(priorPtT, ptT); 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugClearVisited(&fHead); 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with moveMultiples() 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if a span has more than one intersection, merge the other segments' span as needed 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugMoveMultiples(SkPathOpsDebug::GlitchLog* glitches) const { 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* test = &fHead; 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int addCount = test->spanAddsCount(); 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(addCount >= 1); 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (addCount <= 1) { 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* startPtT = test->ptT(); 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testPtT = startPtT; 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { // iterate through all spans associated with start 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppSpan = testPtT->span(); 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSpan->spanAddsCount() == addCount) { 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSpan->deleted()) { 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSegment = oppSpan->segment(); 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSegment == this) { 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // find range of spans to consider merging 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppPrev = oppSpan; 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppFirst = oppSpan; 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((oppPrev = oppPrev->prev())) { 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPrev->spanAddsCount() == addCount) { 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPrev->deleted()) { 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppFirst = oppPrev; 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppNext = oppSpan; 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppLast = oppSpan; 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!roughly_equal(oppNext->t(), oppSpan->t())) { 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppNext->spanAddsCount() == addCount) { 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppNext->deleted()) { 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppLast = oppNext; 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppFirst == oppLast) { 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oppTest = oppFirst; 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppTest == oppSpan) { 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check to see if the candidate meets specific criteria: 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // it contains spans of segments in test's loop but not including 'this' 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppStartPtT = oppTest->ptT(); 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtT = oppStartPtT; 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((oppPtT = oppPtT->next()) != oppStartPtT) { 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppPtTSegment = oppPtT->segment(); 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPtTSegment == this) { 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto tryNextSpan; 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* matchPtT = startPtT; 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (matchPtT->segment() == oppPtTSegment) { 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto foundMatch; 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((matchPtT = matchPtT->next()) != startPtT); 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto tryNextSpan; 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot foundMatch: // merge oppTest and oppSpan 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppSegment->debugValidate(); 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTest->debugMergeMatches(glitches, oppSpan); 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTest->debugAddOpp(glitches, oppSpan); 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppSegment->debugValidate(); 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto checkNextSpan; 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tryNextSpan: 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((testPtT = testPtT->next()) != startPtT); 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotcheckNextSpan: 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ; 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->final() ? nullptr : test->upCast()->next())); 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commented-out lines keep this in sync with moveNearby() 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugMoveNearby(SkPathOpsDebug::GlitchLog* glitches) const { 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // release undeleted spans pointing to this seg that are linked to the primary span 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* spanBase = &fHead; 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = spanBase->ptT(); 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* headPtT = ptT; 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((ptT = ptT->next()) != headPtT) { 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* test = ptT->span(); 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() == this && !ptT->deleted() && test != spanBase 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && test->ptT() == ptT) { 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test->final()) { 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (spanBase == &fHead) { 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyClearAll_Glitch, this); 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// return; 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyReleaseFinal_Glitch, spanBase, ptT); 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (test->prev()) { 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyRelease_Glitch, test, headPtT); 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// break; 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot spanBase = spanBase->upCast()->next(); 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!spanBase->final()); 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This loop looks for adjacent spans which are near by 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot spanBase = &fHead; 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { // iterate through all spans associated with start 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* test = spanBase->upCast()->next(); 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool found; 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->spansNearby(spanBase, test, &found)) { 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (found) { 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test->final()) { 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (spanBase->prev()) { 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyMergeFinal_Glitch, test); 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyClearAll2_Glitch, this); 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // return 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glitches->record(SkPathOpsDebug::kMoveNearbyMerge_Glitch, spanBase); 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot spanBase = test; 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!spanBase->final()); 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugReset() { 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugSetCoinT(int index, SkScalar t) const { 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseIndex = index; 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseMin = SkTMin(t, fDebugBaseMin); 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseMax = SkTMax(t, fDebugBaseMax); 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDebugLastMax < 0 || fDebugLastIndex == index) { 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastIndex = index; 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastMin = SkTMin(t, fDebugLastMin); 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastMax = SkTMax(t, fDebugLastMax); 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ACTIVE_SPANS 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugShowActiveSpans(SkString* str) const { 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (done()) { 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lastId = -1; 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double lastT = -1; 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span = &fHead; 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->done()) { 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (lastId == this->debugID() && lastT == span->t()) { 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastId = this->debugID(); 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastT = span->t(); 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf("%s id=%d", __FUNCTION__, this->debugID()); 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // since endpoints may have be adjusted, show actual computed curves 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDCurve curvePart; 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->subDivide(span, span->next(), &curvePart); 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDPoint* pts = curvePart.fCubic.fPts; 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" (%1.9g,%1.9g", pts[0].fX, pts[0].fY); 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" %1.9g,%1.9g", pts[vIndex].fX, pts[vIndex].fY); 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPath::kConic_Verb == fVerb) { 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" %1.9gf", curvePart.fConic.fWeight); 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(") t=%1.9g tEnd=%1.9g", span->t(), span->next()->t()); 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->windSum() == SK_MinS32) { 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" windSum=?"); 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" windSum=%d", span->windSum()); 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->oppValue() && span->oppSum() == SK_MinS32) { 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" oppSum=?"); 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" oppSum=%d", span->oppSum()); 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" windValue=%d", span->windValue()); 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->oppValue() || span->oppSum() != SK_MinS32) { 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf(" oppValue=%d", span->oppValue()); 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendf("\n"); 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->next()->upCastable())); 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_MARK_DONE 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pt = span->ptT()->fPt; 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s id=%d", fun, this->debugID()); 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (winding == SK_MinS32) { 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", winding); 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" windSum="); 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->windSum() == SK_MinS32) { 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", span->windSum()); 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" windValue=%d\n", span->windValue()); 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oppWinding) { 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pt = span->ptT()->fPt; 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s id=%d", fun, this->debugID()); 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (winding == SK_MinS32) { 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", winding); 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" newOppSum="); 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppWinding == SK_MinS32) { 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", oppWinding); 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" oppSum="); 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->oppSum() == SK_MinS32) { 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", span->oppSum()); 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" windSum="); 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->windSum() == SK_MinS32) { 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("?"); 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", span->windSum()); 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// loop looking for a pair of angle parts that are too close to be sorted 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* This is called after other more simple intersection and angle sorting tests have been exhausted. 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot This should be rarely called -- the test below is thorough and time consuming. 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot This checks the distance between start points; the distance between 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ANGLE 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpAngle::debugCheckNearCoincidence() const { 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* test = this; 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* testSegment = test->segment(); 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testStartT = test->start()->t(); 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testEndT = test->end()->t(); 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testLenSq = testStartPt.distanceSquared(testEndPt); 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testMidT = (testStartT + testEndT) / 2; 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* next = test; 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->fNext) != this) { 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* nextSegment = next->segment(); 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testMidDistSq = testSegment->distSq(testMidT, next); 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double testEndDistSq = testSegment->distSq(testEndT, next); 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextStartT = next->start()->t(); 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double distSq = testStartPt.distanceSquared(nextStartPt); 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextEndT = next->end()->t(); 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextMidT = (nextStartT + nextEndT) / 2; 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextMidDistSq = nextSegment->distSq(nextMidT, test); 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextEndDistSq = nextSegment->distSq(nextEndT, test); 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot testSegment->debugID(), nextSegment->debugID()); 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\n"); 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = test->fNext; 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (test->fNext != this); 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_ANGLE 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString SkOpAngle::debugPart() const { 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString result; 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (this->segment()->verb()) { 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kLine_Verb: 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fPart.fCurve), 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugID()); 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kQuad_Verb: 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fPart.fCurve), 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugID()); 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kConic_Verb: 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result.printf(CONIC_DEBUG_STR " id=%d", 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot CONIC_DEBUG_DATA(fPart.fCurve, fPart.fCurve.fConic.fWeight), 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugID()); 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kCubic_Verb: 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fPart.fCurve), 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugID()); 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SORT 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpAngle::debugLoop() const { 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* first = this; 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* next = this; 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next->dumpOne(true); 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\n"); 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = next->fNext; 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (next && next != first); 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = first; 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next->debugValidate(); 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = next->fNext; 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (next && next != first); 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpAngle::debugValidate() const { 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->globalState()->debugCheckHealth()) { 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* first = this; 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* next = this; 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int wind = 0; 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int opp = 0; 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lastXor = -1; 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lastOppXor = -1; 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->unorderable()) { 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* minSpan = next->start()->starter(next->end()); 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (minSpan->windValue() == SK_MinS32) { 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool op = next->segment()->operand(); 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isXor = next->segment()->isXor(); 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oppXor = next->segment()->oppXor(); 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!DEBUG_LIMIT_WIND_SUM 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool useXor = op ? oppXor : isXor; 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(lastXor == -1 || lastXor == (int) useXor); 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastXor = (int) useXor; 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (useXor) { 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot wind &= 1; 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot useXor = op ? isXor : oppXor; 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastOppXor = (int) useXor; 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (useXor) { 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opp &= 1; 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = next->fNext; 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (next && next != first); 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail); 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail); 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpAngle::debugValidateNext() const { 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if !FORCE_RELEASE 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* first = this; 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpAngle* next = first; 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<const SkOpAngle*>(angles); 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot angles.push(next); 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = next->next(); 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == first) { 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT_RELEASE(!angles.contains(next)); 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!next) { 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpGlobalState* debugState) const { 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail()); 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail()); 1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// sets the span's end to the ptT referenced by the previous-next 1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log, 1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, 1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) const ) const { 1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* origPtT = (this->*getEnd)(); 1422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* origSpan = origPtT->span(); 1423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = origSpan->prev(); 1424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testPtT = prev ? prev->next()->ptT() 1425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : origSpan->upCast()->next()->prev()->ptT(); 1426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (origPtT != testPtT) { 1427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kCorrectEnd_Glitch, this, origPtT, testPtT); 1428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Commented-out lines keep this in sync with correctEnds */ 1433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FIXME: member pointers have fallen out of favor and can be replaced with 1434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// an alternative approach. 1435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// makes all span ends agree with the segment's spans that define them 1436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 1437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTStart, nullptr); 1438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCorrectOneEnd(log, &SkCoincidentSpans::coinPtTEnd, nullptr); 1439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTStart, nullptr); 1440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCorrectOneEnd(log, &SkCoincidentSpans::oppPtTEnd, nullptr); 1441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Commented-out lines keep this in sync with expand */ 1444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// expand the range by checking adjacent spans for coincidence 1445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 1446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool expanded = false; 1447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = coinPtTStart()->segment(); 1448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSegment = oppPtTStart()->segment(); 1449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* start = coinPtTStart()->span()->upCast(); 1451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = start->prev(); 1452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtT; 1453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!prev || !(oppPtT = prev->contains(oppSegment))) { 1454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double midT = (prev->t() + start->t()) / 2; 1457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!segment->isClose(midT, oppSegment)) { 1458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, prev->ptT(), oppPtT); 1461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 1462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (false); // actual continues while expansion is possible 1463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coinPtTEnd()->span(); 1465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 1466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next && next->deleted()) { 1467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtT; 1470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!next || !(oppPtT = next->contains(oppSegment))) { 1471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double midT = (end->t() + next->t()) / 2; 1474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!segment->isClose(midT, oppSegment)) { 1475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, this, next->ptT(), oppPtT); 1478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 1479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (false); // actual continues while expansion is possible 1480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return expanded; 1481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// description below 1484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* base, const SkOpSpanBase* testSpan) const { 1485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testPtT = testSpan->ptT(); 1486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = testPtT; 1487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* baseSeg = base->segment(); 1488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((testPtT = testPtT->next()) != stopPtT) { 1489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* testSeg = testPtT->segment(); 1490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testPtT->deleted()) { 1491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testSeg == baseSeg) { 1494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testPtT->span()->ptT() != testPtT) { 1497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->contains(baseSeg, testSeg, testPtT->fT)) { 1500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // intersect perp with base->ptT() with testPtT->segment() 1503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDVector dxdy = baseSeg->dSlopeAtT(base->t()); 1504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pt = base->pt(); 1505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}}; 1506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntersections i; 1507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i); 1508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < i.used(); ++index) { 1509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double t = i[0][index]; 1510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!between(0, t, 1)) { 1511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint oppPt = i.pt(index); 1514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oppPt.approximatelyEqual(pt)) { 1515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg); 1518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppStart = writableSeg->addT(t); 1519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppStart == testPtT) { 1520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* writableBase = const_cast<SkOpSpan*>(base); 1523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppStart->span()->addOpp(writableBase); 1524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppStart->deleted()) { 1525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* coinSeg = base->segment(); 1528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* oppSeg = oppStart->segment(); 1529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, coinTe, oppTs, oppTe; 1530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (Ordered(coinSeg, oppSeg)) { 1531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = base->t(); 1532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = testSpan->t(); 1533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = oppStart->fT; 1534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = testPtT->fT; 1535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinSeg, oppSeg); 1537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = oppStart->fT; 1538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = testPtT->fT; 1539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = base->t(); 1540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = testSpan->t(); 1541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinTs > coinTe) { 1543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinTs, coinTe); 1544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 1545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool added; 1547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added), false) { 1548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// description below 1556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* ptT) const { 1557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!ptT->span()->upCastable(), ptT->span()); 1558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* base = ptT->span()->upCast(); 1559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = base->prev(); 1560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!prev, ptT->span()); 1561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!prev->isCanceled()) { 1562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, base, base->prev()), false) { 1563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!base->isCanceled()) { 1567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, base, base->next()), false) { 1568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* If A is coincident with B and B includes an endpoint, and A's matching point 1575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot is not the endpoint (i.e., there's an implied line connecting B-end and A) 1576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot then assume that the same implied line may intersect another curve close to B. 1577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Since we only care about coincidence that was undetected, look at the 1578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but 1579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next door) and see if the A matching point is close enough to form another 1580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincident pair. If so, check for a new coincident span between B-end/A ptT loop 1581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot and the adjacent ptT loop. 1582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 1583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const { 1584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* span = fHead; 1585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!span) { 1586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// fTop = span; 1589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// fHead = nullptr; 1590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) { 1592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(1 == span->coinPtTStart()->fT, span); 1593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onEnd = span->coinPtTStart()->fT == 0; 1594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oOnEnd = zero_or_one(span->oppPtTStart()->fT); 1595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (onEnd) { 1596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oOnEnd) { // if both are on end, any nearby intersect was already found 1597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, span->oppPtTStart()), false) { 1598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (oOnEnd) { 1602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, span->coinPtTStart()), false) { 1603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) { 1608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onEnd = span->coinPtTEnd()->fT == 1; 1609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT); 1610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (onEnd) { 1611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oOnEnd) { 1612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, span->oppPtTEnd()), false) { 1613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (oOnEnd) { 1617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->debugAddEndMovedSpans(log, span->coinPtTEnd()), false) { 1618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->next())); 1623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this->restoreHead(); 1624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Commented-out lines keep this in sync with addExpanded */ 1628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for each coincident pair, match the spans 1629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 1630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddExpanded(SkPathOpsDebug::GlitchLog* log) const { 1631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// DEBUG_SET_PHASE(); 1632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = this->fHead; 1633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* startPtT = coin->coinPtTStart(); 1638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oStartPtT = coin->oppPtTStart(); 1639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double priorT = startPtT->fT; 1640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oPriorT = oStartPtT->fT; 1641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startPtT->contains(oStartPtT), coin); 1642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 1643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* start = startPtT->span(); 1644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oStart = oStartPtT->span(); 1645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 1646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 1647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(oEnd->deleted(), coin); 1648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!start->upCastable(), coin); 1649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* test = start->upCast()->next(); 1650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!coin->flipped() && !oStart->upCastable(), coin); 1651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 1652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oTest, coin); 1653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* seg = start->segment(); 1654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oSeg = oStart->segment(); 1655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (test != end || oTest != oEnd) { 1656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* containedOpp = test->ptT()->contains(oSeg); 1657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* containedThis = oTest->ptT()->contains(seg); 1658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!containedOpp || !containedThis) { 1659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // choose the ends, or the first common pt-t list shared by both 1660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextT, oNextT; 1661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containedOpp) { 1662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = test->t(); 1663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = containedOpp->fT; 1664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (containedThis) { 1665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = containedThis->fT; 1666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = oTest->t(); 1667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // iterate through until a pt-t list found that contains the other 1669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* walk = test; 1670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* walkOpp; 1671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!walk->upCastable(), coin); 1673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot walk = walk->upCast()->next(); 1674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!(walkOpp = walk->ptT()->contains(oSeg)) 1675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && walk != coin->coinPtTEnd()->span()); 1676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!walkOpp, coin); 1677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = walk->t(); 1678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = walkOpp->fT; 1679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // use t ranges to guess which one is missing 1681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double startRange = nextT - priorT; 1682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startRange, coin); 1683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double startPart = (test->t() - priorT) / startRange; 1684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oStartRange = oNextT - oPriorT; 1685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oStartRange, coin); 1686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 1687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(startPart == oStartPart, coin); 1688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart 1689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : !!containedThis; 1690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool startOver = false; 1691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot addToOpp ? log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oPriorT + oStartRange * startPart, test) 1693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : log->record(SkPathOpsDebug::kAddExpandedCoin_Glitch, 1694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorT + startRange * oStartPart, oTest); 1695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FAIL_IF(!success, coin); 1696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startOver) { 1697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = start; 1698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oTest = oStart; 1699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot end = coin->coinPtTEnd()->span(); 1701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oEnd = coin->oppPtTEnd()->span(); 1702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test != end) { 1704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!test->upCastable(), coin); 1705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorT = test->t(); 1706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = test->upCast()->next(); 1707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oTest != oEnd) { 1709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oPriorT = oTest->t(); 1710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oTest = coin->flipped() ? oTest->prev() : oTest->upCast()->next(); 1711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oTest, coin); 1712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Commented-out lines keep this in sync addIfMissing() */ 1719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// note that over1s, over1e, over2s, over2e are ordered 1720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddIfMissing(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s, 1721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added, 1722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* over1e, const SkOpPtT* over2e) const { 1723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(tStart < tEnd); 1724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->fT < over1e->fT); 1725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over1s->fT, tStart, over1e->fT)); 1726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 1727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over2s->fT < over2e->fT); 1728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over2s->fT, tStart, over2e->fT)); 1729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 1730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() == over1e->segment()); 1731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over2s->segment() == over2e->segment()); 1732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() == over2s->segment()); 1733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() != coinSeg); 1734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() != oppSeg); 1735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coinSeg != oppSeg); 1736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, coinTe, oppTs, oppTe; 1737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 1738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 1739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg->collapsed(coinTs, coinTe)) { 1740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, coinSeg); 1741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 1743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 1744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg->collapsed(oppTs, oppTe)) { 1745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return log->record(SkPathOpsDebug::kAddIfCollapsed_Glitch, oppSeg); 1746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinTs > coinTe) { 1748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinTs, coinTe); 1749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 1750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->debugAddOrOverlap(log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added 1752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ); 1753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Commented-out lines keep this in sync addOrOverlap() */ 1756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 1757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 1758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log, 1759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 1760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, double coinTe, double oppTs, double oppTe, bool* added) const { 1761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SkCoincidentSpans*> overlaps; 1762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!fTop); // this is (correctly) reversed in addifMissing() 1763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, 1764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &overlaps)) { 1765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 1768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe, oppTs, oppTe, &overlaps)) { 1769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 1772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 1773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* test = overlaps[index]; 1774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 1775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTStart()); 1776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 1778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->coinPtTEnd()); 1779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->flipped() 1781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 1782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 1783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTStart()); 1784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->flipped() 1786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 1787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 1788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddOrOverlap_Glitch, overlap, test->oppPtTEnd()); 1789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fHead) { this->debugRelease(log, fHead, test); 1791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugRelease(log, fTop, test); 1792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 1795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 1796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg); 1797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(cs != ce || !cs, coinSeg); 1798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 1799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 1800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg); 1801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(true || !cs || !cs->deleted()); 1802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(true || !os || !os->deleted()); 1803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(true || !ce || !ce->deleted()); 1804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(true || !oe || !oe->deleted()); 1805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 1806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 1807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg); 1808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(csExisting && (csExisting == ce || 1809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg); 1810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(ceExisting && (ceExisting == cs || 1811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ceExisting->contains(csExisting ? csExisting : cs)), coinSeg); 1812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 1813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 1814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg); 1815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(osExisting && (osExisting == oe || 1816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg); 1817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(oeExisting && (oeExisting == os || 1818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oeExisting->contains(osExisting ? osExisting : os)), oppSeg); 1819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false; 1820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 1821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!cs || !os) { 1822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!cs) 1823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cs = coinSeg->debugAddT(coinTs, log); 1824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!os) 1825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot os = oppSeg->debugAddT(oppTs, log); 1826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 1827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (cs && os) cs->span()->debugAddOpp(log, os->span()); 1828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// cs = csWritable; 1829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// os = osWritable->active(); 1830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg); 1831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ce || !oe) { 1833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ce) 1834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ce = coinSeg->debugAddT(coinTe, log); 1835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oe) 1836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oe = oppSeg->debugAddT(oppTe, log); 1837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ce && oe) ce->span()->debugAddOpp(log, oe->span()); 1838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// ce = ceWritable; 1839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// oe = oeWritable; 1840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 1842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(csDeleted, coinSeg); 1843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(osDeleted, oppSeg); 1844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(ceDeleted, coinSeg); 1845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(oeDeleted, oppSeg); 1846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg); 1847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool result = true; 1848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap) { 1849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTStart()->segment() == coinSeg) { 1850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 1851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppTs > oppTe) { 1853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinTs, coinTe); 1854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 1855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddMissingExtend_Glitch, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe); 1857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 && DEBUG_COINCIDENCE_VERBOSE 1859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (result) { 1860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlap->debugShow(); 1861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kAddMissingCoin_Glitch, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe); 1865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 && DEBUG_COINCIDENCE_VERBOSE 1866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead->debugShow(); 1867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 1870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (void) result; 1871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Extra commented-out lines keep this in sync with addMissing() 1874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* detects overlaps of different coincident runs on same segment */ 1875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* does not detect overlaps for pairs without any segments in common */ 1876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// returns true if caller should loop again 1877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugAddMissing(SkPathOpsDebug::GlitchLog* log, bool* added) const { 1878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* outer = fHead; 1879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *added = false; 1880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!outer) { 1881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fTop = outer; 1884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fHead = nullptr; 1885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // addifmissing can modify the list that this is walking 1887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // save head so that walker can iterate over old data unperturbed 1888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // addifmissing adds to head freely then add saved head in the end 1889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ocs = outer->coinPtTStart(); 1890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ocs->deleted()); 1891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerCoin = ocs->segment(); 1892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 1893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oos = outer->oppPtTStart(); 1894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oos->deleted()) { 1895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerOpp = oos->segment(); 1898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!outerOpp->done()); 1899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 1900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 1901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* inner = outer; 1902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((inner = inner->next())) { 1903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 1904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double overS, overE; 1905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ics = inner->coinPtTStart(); 1906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ics->deleted()); 1907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerCoin = ics->segment(); 1908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!innerCoin->done()); 1909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ios = inner->oppPtTStart(); 1910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ios->deleted()); 1911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerOpp = ios->segment(); 1912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!innerOpp->done()); 1913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin); 1914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 1915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerCoin == innerCoin) { 1916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oce = outer->coinPtTEnd(); 1917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oce->deleted()) { 1918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ice = inner->coinPtTEnd(); 1921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ice->deleted()); 1922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) { 1923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugAddIfMissing(log, ocs->starter(oce), ics->starter(ice), 1924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerOpp, innerOpp, added, 1925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ocs->debugEnder(oce), 1926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ics->debugEnder(ice)); 1927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerCoin == innerOpp) { 1929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oce = outer->coinPtTEnd(); 1930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!oce->deleted()); 1931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ioe = inner->oppPtTEnd(); 1932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ioe->deleted()); 1933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) { 1934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugAddIfMissing(log, ocs->starter(oce), ios->starter(ioe), 1935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerOpp, innerCoin, added, 1936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ocs->debugEnder(oce), 1937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ios->debugEnder(ioe)); 1938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerOpp == innerCoin) { 1940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ooe = outer->oppPtTEnd(); 1941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ooe->deleted()); 1942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ice = inner->coinPtTEnd(); 1943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ice->deleted()); 1944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(outerCoin != innerOpp); 1945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 1946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugAddIfMissing(log, oos->starter(ooe), ics->starter(ice), 1947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerCoin, innerOpp, added, 1948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oos->debugEnder(ooe), 1949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ics->debugEnder(ice)); 1950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerOpp == innerOpp) { 1952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ooe = outer->oppPtTEnd(); 1953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ooe->deleted()); 1954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ioe = inner->oppPtTEnd(); 1955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ioe->deleted()) { 1956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(outerCoin != innerCoin); 1959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 1960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugAddIfMissing(log, oos->starter(ooe), ios->starter(ioe), 1961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerCoin, innerCoin, added, 1962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oos->debugEnder(ooe), 1963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ios->debugEnder(ioe)); 1964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 1967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((outer = outer->next())); 1969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // this->restoreHead(); 1970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with release() 1974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const { 1975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* head = coin; 1976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* prev = nullptr; 1977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* next; 1978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = coin->next(); 1980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin == remove) { 1981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (prev) { 1982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// prev->setNext(next); 1983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (head == fHead) { 1984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// fHead = next; 1985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// fTop = next; 1987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 1989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = coin; 1991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = next)); 1992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugRelease(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const { 1996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = fHead; 1997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart()->segment() == deleted 2002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->coinPtTEnd()->segment() == deleted 2003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->oppPtTStart()->segment() == deleted 2004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->oppPtTEnd()->segment() == deleted) { 2005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kReleasedSpan_Glitch, coin); 2006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 2008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with expand() 2011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// expand the range by checking adjacent spans for coincidence 2012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::debugExpand(SkPathOpsDebug::GlitchLog* log) const { 2013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = fHead; 2014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 2015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 2016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool expanded = false; 2018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->debugExpand(log)) { 2020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check to see if multiple spans expanded so they are now identical 2021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* test = fHead; 2022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin == test) { 2024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart() == test->coinPtTStart() 2027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && coin->oppPtTStart() == test->oppPtTStart()) { 2028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (log) log->record(SkPathOpsDebug::kExpandCoin_Glitch, fHead, test->coinPtTStart()); 2029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next())); 2032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 2033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 2035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return expanded; 2036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with mark() 2039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 2040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugMark(SkPathOpsDebug::GlitchLog* log) const { 2041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = fHead; 2042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 2043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable(), coin); 2047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 2048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(start->deleted()); 2049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 2050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(end->deleted()); 2051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 2052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(oStart->deleted()); 2053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 2054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(oEnd->deleted()); 2055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool flipped = coin->flipped(); 2056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (flipped) { 2057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oStart, oEnd); 2058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* coin and opp spans may not match up. Mark the ends, and then let the interior 2060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot get marked as many times as the spans allow */ 2061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start->debugInsertCoincidence(log, oStart->upCast()); 2062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot end->debugInsertCoinEnd(log, oEnd); 2063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = start->segment(); 2064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oSegment = oStart->segment(); 2065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* next = start; 2066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oNext = oStart; 2067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool ordered; 2068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!coin->ordered(&ordered), coin); 2069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->upCast()->next()) != end) { 2070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!next->upCastable(), coin); 2071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->upCast()->debugInsertCoincidence(log, oSegment, flipped, ordered), false) { 2072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((oNext = oNext->upCast()->next()) != oEnd) { 2076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oNext->upCastable(), coin); 2077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oNext->upCast()->debugInsertCoincidence(log, segment, flipped, ordered), false) { 2078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 2082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with markCollapsed() 2088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const { 2089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* head = coin; 2090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (coin) { 2091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->collapsed(test)) { 2092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 2093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 2094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 2096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kCollapsedCoin_Glitch, coin); 2097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugRelease(log, head, coin); 2099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin = coin->next(); 2101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with markCollapsed() 2105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugMarkCollapsed(SkPathOpsDebug::GlitchLog* log, const SkOpPtT* test) const { 2106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugMarkCollapsed(log, fHead, test); 2107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugMarkCollapsed(log, fTop, test); 2108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::debugShow() const { 2112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(), 2113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinPtTStart()->fT, coinPtTEnd()->fT); 2114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(), 2115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppPtTStart()->fT, oppPtTEnd()->fT); 2116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugShowCoincidence() const { 2119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* span = fHead; 2121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (span) { 2122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->debugShow(); 2123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = span->next(); 2124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end, 2130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oStart, double oEnd, const SkOpSegment* oSegment, 2131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog* log) { 2132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(next != end); 2133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!next->contains(end) || log); 2134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->t() > end->t()) { 2135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(next, end); 2136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = next->ptT(); 2139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int index = 0; 2140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool somethingBetween = false; 2141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++index; 2143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* checkPtT = next->ptT(); 2145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT == checkPtT) { 2146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool looped = false; 2149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int check = 0; check < index; ++check) { 2150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((looped = checkPtT == ptT)) { 2151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot checkPtT = checkPtT->next(); 2154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (looped) { 2156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0); 2157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->deleted()) { 2160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() != oSegment) { 2163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot somethingBetween |= between(oStart, ptT->fT, oEnd); 2166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 2167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(somethingBetween); 2168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (next != end && (next = next->upCast()->next())); 2169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugCheckOverlap(const SkCoincidentSpans* test, const SkCoincidentSpans* list, 2172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog* log) { 2173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!list) { 2174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg = test->coinPtTStart()->segment(); 2177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coinSeg == test->coinPtTEnd()->segment()); 2178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSeg = test->oppPtTStart()->segment(); 2179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(oppSeg == test->oppPtTEnd()->segment()); 2180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coinSeg != test->oppPtTStart()->segment()); 2181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(double tcs = test->coinPtTStart()->fT); 2182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(0, tcs, 1)); 2183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(double tce = test->coinPtTEnd()->fT); 2184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(0, tce, 1)); 2185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(tcs < tce); 2186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double tos = test->oppPtTStart()->fT; 2187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(0, tos, 1)); 2188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double toe = test->oppPtTEnd()->fT; 2189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(0, toe, 1)); 2190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(tos != toe); 2191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (tos > toe) { 2192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(tos, toe); 2193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double lcs, lce, los, loe; 2196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg == list->coinPtTStart()->segment()) { 2197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg != list->oppPtTStart()->segment()) { 2198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lcs = list->coinPtTStart()->fT; 2201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lce = list->coinPtTEnd()->fT; 2202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot los = list->oppPtTStart()->fT; 2203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loe = list->oppPtTEnd()->fT; 2204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (los > loe) { 2205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(los, loe); 2206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (coinSeg == list->oppPtTStart()->segment()) { 2208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg != list->coinPtTStart()->segment()) { 2209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lcs = list->oppPtTStart()->fT; 2212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lce = list->oppPtTEnd()->fT; 2213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (lcs > lce) { 2214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(lcs, lce); 2215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot los = list->coinPtTStart()->fT; 2217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loe = list->coinPtTEnd()->fT; 2218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 2219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(tce < lcs || lce < tcs); 2222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(toe < los || loe < tos); 2223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((list = list->next())); 2224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugCheckOverlapTop(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog* log) { 2229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check for overlapping coincident spans 2230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* test = head; 2231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (test) { 2232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* next = test->next(); 2233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckOverlap(test, next, log); 2234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckOverlap(test, opt, log); 2235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = next; 2236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog* log) { 2241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // look for pts inside coincident spans that are not inside the opposite spans 2242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = head; 2243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (coin) { 2244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkOpCoincidence::Ordered(coin->coinPtTStart()->segment(), 2245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->oppPtTStart()->segment())); 2246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->coinPtTStart()->span()->ptT() == coin->coinPtTStart()); 2247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); 2248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); 2249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); 2250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin = coin->next(); 2251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckOverlapTop(head, opt, log); 2253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugValidate() const { 2257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugValidate(fHead, fTop, nullptr); 2259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugValidate(fTop, nullptr, nullptr); 2260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, 2265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathOpsDebug::GlitchLog* log) { 2266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // look for pts inside coincident spans that are not inside the opposite spans 2267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = head; 2268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (coin) { 2269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), 2270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), 2271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log); 2272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), 2273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), 2274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log); 2275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin = coin->next(); 2276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckOverlapTop(head, opt, log); 2278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugCheckBetween() const { 2282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fGlobalState->debugCheckHealth()) { 2284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckBetween(fHead, fTop, nullptr); 2287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckBetween(fTop, nullptr, nullptr); 2288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpContour::debugCheckHealth(SkPathOpsDebug::GlitchLog* log) const { 2293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = &fHead; 2294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment->debugCheckHealth(log); 2296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((segment = segment->next())); 2297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugCheckValid(SkPathOpsDebug::GlitchLog* log) const { 2300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 2301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugValidate(fHead, fTop, log); 2302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugValidate(fTop, nullptr, log); 2303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const { 2307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* coin = fHead; 2308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 2309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->debugCorrectEnds(log); 2313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 2314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// commmented-out lines keep this aligned with missingCoincidence() 2317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpContour::debugMissingCoincidence(SkPathOpsDebug::GlitchLog* log) const { 2318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(fCount > 0); 2319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = &fHead; 2320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// bool result = false; 2321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->debugMissingCoincidence(log), false) { 2323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// result = true; 2324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment = segment->next(); 2326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (segment); 2327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpContour::debugMoveMultiples(SkPathOpsDebug::GlitchLog* log) const { 2331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCount > 0); 2332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = &fHead; 2333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->debugMoveMultiples(log), false) { 2335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((segment = segment->next())); 2338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpContour::debugMoveNearby(SkPathOpsDebug::GlitchLog* log) const { 2342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCount > 0); 2343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = &fHead; 2344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment->debugMoveNearby(log); 2346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((segment = segment->next())); 2347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugResetCoinT() const { 2352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseIndex = -1; 2353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseMin = 1; 2354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugBaseMax = -1; 2355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastIndex = -1; 2356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastMin = 1; 2357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDebugLastMax = -1; 2358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSegment::debugValidate() const { 2362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 2364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span = &fHead; 2365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->debugResetCoinT(); 2367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!span->final() && (span = span->upCast()->next())); 2368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = &fHead; 2369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int index = 0; 2370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->debugSetCoinT(index++); 2372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!span->final() && (span = span->upCast()->next())); 2373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->globalState()->debugCheckHealth()) { 2377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 2381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* span = &fHead; 2382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double lastT = -1; 2383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* prev = nullptr; 2384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = 0; 2385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int done = 0; 2386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!span->final()) { 2388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++count; 2389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot done += span->upCast()->done() ? 1 : 0; 2390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(span->segment() == this); 2392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!prev || prev->upCast()->next() == span); 2393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!prev || prev == span->prev()); 2394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = span; 2395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double t = span->ptT()->fT; 2396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(lastT < t); 2397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lastT = t; 2398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->debugValidate(); 2399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!span->final() && (span = span->upCast()->next())); 2400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(count == fCount); 2401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(done == fDoneCount); 2402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(count >= fDoneCount); 2403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(span->final()); 2404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span->debugValidate(); 2405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with addOpp() 2411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugAddOpp(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 2412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 2413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oppPrev) { 2414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugMergeMatches(log, opp); 2417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->ptT()->debugAddOpp(opp->ptT(), oppPrev); 2418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCheckForCollapsedCoincidence(log); 2419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with checkForCollapsedCoincidence() 2422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* log) const { 2423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpCoincidence* coins = this->globalState()->coincidence(); 2424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coins->isEmpty()) { 2425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the insert above may have put both ends of a coincident run in the same span 2428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for each coincident ptT in loop; see if its opposite in is also in the loop 2429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this implementation is the motivation for marking that a ptT is referenced by a coincident span 2430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* head = this->ptT(); 2431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* test = head; 2432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!test->coincident()) { 2434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coins->debugMarkCollapsed(log, test); 2437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next()) != head); 2438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpanBase::debugCoinEndLoopCheck() const { 2442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int loop = 0; 2443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* next = this; 2444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* nextCoin; 2445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextCoin = next->fCoinEnd; 2447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 2448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int check = 1; check < loop - 1; ++check) { 2449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* checkCoin = this->fCoinEnd; 2450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* innerCoin = checkCoin; 2451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int inner = check + 1; inner < loop; ++inner) { 2452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot innerCoin = innerCoin->fCoinEnd; 2453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (checkCoin == innerCoin) { 2454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("*** bad coincident end loop ***\n"); 2455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 2456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++loop; 2460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((next = nextCoin) && next != this); 2461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 2462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with insertCoinEnd() 2466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* coin) const { 2467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containsCoinEnd(coin)) { 2468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(coin->containsCoinEnd(this)); 2469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 2472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(this != coin); 2473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMarkCoinEnd_Glitch, this, coin); 2474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// coin->fCoinEnd = this->fCoinEnd; 2475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this->fCoinEnd = coinNext; 2476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 2477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with mergeMatches() 2480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Look to see if pt-t linked list contains same segment more than once 2481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if so, and if each pt-t is directly pointed to by spans in that segment, 2482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// merge them 2483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// keep the points, but remove spans so that the segment doesn't have 2 or more 2484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// spans pointing to the same pt-t loop at different loop elements 2485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugMergeMatches(SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const { 2486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* test = &fPtT; 2487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testNext; 2488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stop = test; 2489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot testNext = test->next(); 2491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test->deleted()) { 2492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* testBase = test->span(); 2495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(testBase->ptT() == test); 2496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = test->segment(); 2497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->done()) { 2498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* inner = opp->ptT(); 2501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* innerStop = inner; 2502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (inner->segment() != segment) { 2504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (inner->deleted()) { 2507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* innerBase = inner->span(); 2510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(innerBase->ptT() == inner); 2511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // when the intersection is first detected, the span base is marked if there are 2512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // more than one point in the intersection. 2513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) { 2514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!zero_or_one(inner->fT)) { 2515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMergeMatches_Glitch, innerBase, test); 2516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 2517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(inner->fT != test->fT); 2518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!zero_or_one(test->fT)) { 2519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMergeMatches_Glitch, testBase, inner); 2520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 2521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMergeMatches_Glitch, segment); 2522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDEBUGCODE(testBase->debugSetDeleted()); 2523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// test->setDeleted(); 2524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDEBUGCODE(innerBase->debugSetDeleted()); 2525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// inner->setDeleted(); 2526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG // assert if another undeleted entry points to segment 2529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* debugInner = inner; 2530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((debugInner = debugInner->next()) != innerStop) { 2531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (debugInner->segment() != segment) { 2532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (debugInner->deleted()) { 2535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(0); 2538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// } 2542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((inner = inner->next()) != innerStop); 2544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = testNext) != stop); 2545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugCheckForCollapsedCoincidence(log); 2546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugResetCoinT() const { 2551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = &fPtT; 2553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT->debugResetCoinT(); 2555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (ptT != &fPtT); 2557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugSetCoinT(int index) const { 2561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = &fPtT; 2563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ptT->deleted()) { 2565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT->debugSetCoinT(index); 2566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (ptT != &fPtT); 2569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 2573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = *endPtr; 2574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() == end->segment()); 2575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* result; 2576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (t() < end->t()) { 2577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = this; 2578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 2579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = end; 2580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *endPtr = this; 2581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result->upCast(); 2583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpanBase::debugValidate() const { 2586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->globalState()->debugCheckHealth()) { 2588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 2592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = &fPtT; 2593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(ptT->span() == this); 2594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 2596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT->debugValidate(); 2597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (ptT != &fPtT); 2599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->debugCoinEndLoopCheck()); 2600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->final()) { 2601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->upCast()->debugCoinLoopCheck()); 2602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFromAngle) { 2604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFromAngle->debugValidate(); 2605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->final() && this->upCast()->toAngle()) { 2607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->upCast()->toAngle()->debugValidate(); 2608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpSpan::debugCoinLoopCheck() const { 2613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int loop = 0; 2614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* next = this; 2615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* nextCoin; 2616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextCoin = next->fCoincident; 2618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 2619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int check = 1; check < loop - 1; ++check) { 2620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* checkCoin = this->fCoincident; 2621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* innerCoin = checkCoin; 2622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int inner = check + 1; inner < loop; ++inner) { 2623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot innerCoin = innerCoin->fCoincident; 2624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (checkCoin == innerCoin) { 2625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("*** bad coincident loop ***\n"); 2626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 2627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++loop; 2631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((next = nextCoin) && next != this); 2632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 2633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with insertCoincidence() in header 2637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSpan* coin) const { 2638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containsCoincidence(coin)) { 2639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(coin->containsCoincidence(this)); 2640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 2643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkASSERT(this != coin); 2644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMarkCoinStart_Glitch, this, coin); 2645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// coin->fCoincident = this->fCoincident; 2646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this->fCoincident = coinNext; 2647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debugValidate(); 2648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with insertCoincidence() 2651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpSpan::debugInsertCoincidence(SkPathOpsDebug::GlitchLog* log, const SkOpSegment* segment, bool flipped, bool ordered) const { 2652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->containsCoincidence(segment)) { 2653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* next = &fPtT; 2656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->next()) != &fPtT) { 2657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next->segment() == segment) { 2658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* span; 2659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* base = next->span(); 2660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ordered) { 2661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* spanEnd = fNext->contains(segment)->span(); 2662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT()); 2663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!start->span()->upCastable(), this); 2664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = const_cast<SkOpSpan*>(start->span()->upCast()); 2665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot else if (flipped) { 2667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = base->prev(); 2668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!span, this); 2669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot else { 2671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!base->upCastable(), this); 2672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot span = base->upCast(); 2673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMarkCoinInsert_Glitch, span); 2675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COIN 2679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot log->record(SkPathOpsDebug::kMarkCoinMissing_Glitch, segment, this); 2680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// called only by test code 2686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkIntersections::debugCoincidentUsed() const { 2687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fIsCoincident[0]) { 2688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!fIsCoincident[1]); 2689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 2690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = 0; 2692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(int count2 = 0;) 2693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < fUsed; ++index) { 2694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fIsCoincident[0] & (1 << index)) { 2695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++count; 2696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 2698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fIsCoincident[1] & (1 << index)) { 2699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++count2; 2700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(count == count2); 2704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return count; 2705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpContour.h" 2708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with addOpp() 2710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const { 2711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(const SkOpPtT* oldNext = this->fNext); 2712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != opp); 2713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// this->fNext = opp; 2714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(oppPrev != oldNext); 2715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// oppPrev->fNext = oldNext; 2716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpPtT::debugContains(const SkOpPtT* check) const { 2719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this != check); 2720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 2721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int links = 0; 2722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT == check) { 2725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 2726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++links; 2728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* test = this; 2729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < links; ++index) { 2730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT == test) { 2731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 2732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = test->next(); 2734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 2736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 2739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->segment() != check); 2740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ptT = this; 2741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int links = 0; 2742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT = ptT->next(); 2744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT->segment() == check) { 2745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ptT; 2746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++links; 2748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* test = this; 2749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < links; ++index) { 2750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ptT == test) { 2751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 2752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = test->next(); 2754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 2756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const { 2759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fT < end->fT ? end : this; 2760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkOpPtT::debugLoopLimit(bool report) const { 2763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int loop = 0; 2764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* next = this; 2765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 2766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int check = 1; check < loop - 1; ++check) { 2767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* checkPtT = this->fNext; 2768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* innerPtT = checkPtT; 2769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int inner = check + 1; inner < loop; ++inner) { 2770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot innerPtT = innerPtT->fNext; 2771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (checkPtT == innerPtT) { 2772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (report) { 2773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("*** bad ptT loop ***\n"); 2774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return loop; 2776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // there's nothing wrong with extremely large loop counts -- but this may appear to hang 2780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // by taking a very long time to figure out that no loop entry is a duplicate 2781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // -- and it's likely that a large loop count is indicative of a bug somewhere 2782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (++loop > 1000) { 2783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("*** loop count exceeds 1000 ***\n"); 2784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 1000; 2785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((next = next->fNext) && next != this); 2787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 2788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkOpPtT::debugOppPrev(const SkOpPtT* opp) const { 2791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->oppPrev(const_cast<SkOpPtT*>(opp)); 2792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::debugResetCoinT() const { 2795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugResetCoinT(); 2797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::debugSetCoinT(int index) const { 2801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_ORDER 2802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->segment()->debugSetCoinT(index, fT); 2803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpPtT::debugValidate() const { 2807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 2808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->globalState()->debugCheckHealth()) { 2809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_VALIDATE 2813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPhase phase = contour()->globalState()->phase(); 2814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (phase == SkOpPhase::kIntersecting || phase == SkOpPhase::kFixWinding) { 2815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fNext); 2818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fNext != this); 2819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fNext->fNext); 2820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(debugLoopLimit(false) == 0); 2821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void output_scalar(SkScalar num) { 2825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (num == (int) num) { 2826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%d", (int) num); 2827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 2828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString str; 2829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str.printf("%1.9g", num); 2830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int width = (int) str.size(); 2831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* cStr = str.c_str(); 2832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (cStr[width - 1] == '0') { 2833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --width; 2834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str.resize(width); 2836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("%sf", str.c_str()); 2837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void output_points(const SkPoint* pts, int count) { 2841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < count; ++index) { 2842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_scalar(pts[index].fX); 2843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(", "); 2844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_scalar(pts[index].fY); 2845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (index + 1 < count) { 2846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(", "); 2847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 2852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t verb; 2853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint pts[4]; 2854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 2855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (verb) { 2856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kMove_Verb: 2857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.moveTo(", pathName); 2858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_points(&pts[0], 1); 2859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(");\n"); 2860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 2861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kLine_Verb: 2862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.lineTo(", pathName); 2863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_points(&pts[1], 1); 2864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(");\n"); 2865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kQuad_Verb: 2867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.quadTo(", pathName); 2868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_points(&pts[1], 2); 2869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(");\n"); 2870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kConic_Verb: 2872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.conicTo(", pathName); 2873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_points(&pts[1], 2); 2874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(", %1.9gf);\n", iter.conicWeight()); 2875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kCubic_Verb: 2877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.cubicTo(", pathName); 2878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot output_points(&pts[1], 3); 2879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(");\n"); 2880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPath::kClose_Verb: 2882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.close();\n", pathName); 2883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 2884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 2885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("bad verb"); 2886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* gFillTypeStr[] = { 2892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kWinding_FillType", 2893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kEvenOdd_FillType", 2894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kInverseWinding_FillType", 2895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "kInverseEvenOdd_FillType" 2896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 2897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 2899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath::RawIter iter(path); 2900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SUPPORT_RECT_CONTOUR_DETECTION 0 2901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SUPPORT_RECT_CONTOUR_DETECTION 2902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 2903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rectCount > 0) { 2904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SkRect> rects; 2905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SkPath::Direction> directions; 2906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rects.setCount(rectCount); 2907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot directions.setCount(rectCount); 2908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.rectContours(rects.begin(), directions.begin()); 2909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int contour = 0; contour < rectCount; ++contour) { 2910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect& rect = rects[contour]; 2911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 2912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 2913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 2914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 2916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 2918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath::FillType fillType = path.getFillType(); 2919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 2920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (includeDeclaration) { 2921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" SkPath %s;\n", name); 2922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 2924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot iter.setPath(path); 2925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot showPathContours(iter, name); 2926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_DUMP_VERIFY 2929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkData.h" 2930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h" 2931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) { 2933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDynamicMemoryWStream wStream; 2934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.dump(&wStream, force, dumpAsHex); 2935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data(wStream.detachAsData()); 2936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data()); 2937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int dumpID = 0; 2940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DumpOp(const SkPath& one, const SkPath& two, SkPathOp op, 2942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* testName) { 2943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FILE* file = sk_fopen("op_dump.txt", kWrite_SkFILE_Flag); 2944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpOp(file, one, two, op, testName); 2945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op, 2948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* testName) { 2949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* name = testName ? testName : "op"; 2950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, 2951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 2952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot name, ++dumpID); 2953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " SkPath path;\n"); 2954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType()); 2955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dump_path(file, one, false, true); 2956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " SkPath path1(path);\n"); 2957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " path.reset();\n"); 2958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType()); 2959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dump_path(file, two, false, true); 2960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " SkPath path2(path);\n"); 2961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op); 2962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, "}\n\n"); 2963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fclose(file); 2964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DumpSimplify(const SkPath& path, const char* testName) { 2967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FILE* file = sk_fopen("simplify_dump.txt", kWrite_SkFILE_Flag); 2968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpSimplify(file, path, testName); 2969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::DumpSimplify(FILE* file, const SkPath& path, const char* testName) { 2972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* name = testName ? testName : "simplify"; 2973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, 2974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n", 2975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot name, ++dumpID); 2976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " SkPath path;\n"); 2977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", path.getFillType()); 2978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dump_path(file, path, false, true); 2979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, " testSimplify(reporter, path, filename);\n"); 2980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(file, "}\n\n"); 2981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fclose(file); 2982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 2983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h" 2985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 2986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h" 2987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst int bitWidth = 64; 2989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst int bitHeight = 64; 2990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void debug_scale_matrix(const SkPath& one, const SkPath* two, SkMatrix& scale) { 2992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect larger = one.getBounds(); 2993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (two) { 2994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot larger.join(two->getBounds()); 2995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 2996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar largerWidth = larger.width(); 2997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (largerWidth < 4) { 2998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot largerWidth = 4; 2999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar largerHeight = larger.height(); 3001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (largerHeight < 4) { 3002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot largerHeight = 4; 3003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar hScale = (bitWidth - 2) / largerWidth; 3005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar vScale = (bitHeight - 2) / largerHeight; 3006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scale.reset(); 3007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scale.preScale(hScale, vScale); 3008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot larger.fLeft *= hScale; 3009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot larger.fRight *= hScale; 3010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot larger.fTop *= vScale; 3011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot larger.fBottom *= vScale; 3012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft 3013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : 16000 < larger.fRight ? 16000 - larger.fRight : 0; 3014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop 3015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0; 3016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scale.preTranslate(dx, dy); 3017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) { 3020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (bits.width() == 0) { 3021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bits.allocN32Pixels(bitWidth * 2, bitHeight); 3022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas canvas(bits); 3024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.drawColor(SK_ColorWHITE); 3025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint; 3026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.save(); 3027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect& bounds1 = one.getBounds(); 3028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); 3029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.drawPath(one, paint); 3030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.restore(); 3031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.save(); 3032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1); 3033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.drawPath(two, paint); 3034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.restore(); 3035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int errors = 0; 3036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int y = 0; y < bitHeight - 1; ++y) { 3037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* addr1 = bits.getAddr32(0, y); 3038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* addr2 = bits.getAddr32(0, y + 1); 3039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* addr3 = bits.getAddr32(bitWidth, y); 3040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1); 3041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int x = 0; x < bitWidth - 1; ++x) { 3042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // count 2x2 blocks 3043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool err = addr1[x] != addr3[x]; 3044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err) { 3045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot errors += addr1[x + 1] != addr3[x + 1] 3046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1]; 3047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return errors; 3051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op) { 3054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("// Op did not expect failure\n"); 3055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpOp(stderr, one, two, op, "opTest"); 3056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fflush(stderr); 3057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op, 3060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPath& result) { 3061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath pathOut, scaledPathOut; 3062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion rgnA, rgnB, openClip, rgnOut; 3063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot openClip.setRect(-16000, -16000, 16000, 16000); 3064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnA.setPath(one, openClip); 3065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnB.setPath(two, openClip); 3066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnOut.op(rgnA, rgnB, (SkRegion::Op) op); 3067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnOut.getBoundaryPath(&pathOut); 3068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix scale; 3069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debug_scale_matrix(one, &two, scale); 3070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; 3071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath scaledA, scaledB; 3072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledA.addPath(one, scale); 3073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledA.setFillType(one.getFillType()); 3074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledB.addPath(two, scale); 3075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledB.setFillType(two.getFillType()); 3076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnA.setPath(scaledA, openClip); 3077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnB.setPath(scaledB, openClip); 3078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op); 3079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnOut.getBoundaryPath(&scaledPathOut); 3080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bitmap; 3081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath scaledOut; 3082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledOut.addPath(result, scale); 3083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledOut.setFillType(result.getFillType()); 3084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 3085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int MAX_ERRORS = 9; 3086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (errors > MAX_ERRORS) { 3087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, "// Op did not expect errors=%d\n", errors); 3088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpOp(stderr, one, two, op, "opTest"); 3089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fflush(stderr); 3090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::ReportSimplifyFail(const SkPath& path) { 3094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("// Simplify did not expect failure\n"); 3095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpSimplify(stderr, path, "simplifyTest"); 3096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fflush(stderr); 3097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) { 3100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath pathOut, scaledPathOut; 3101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion rgnA, openClip, rgnOut; 3102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot openClip.setRect(-16000, -16000, 16000, 16000); 3103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnA.setPath(path, openClip); 3104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rgnOut.getBoundaryPath(&pathOut); 3105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix scale; 3106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot debug_scale_matrix(path, nullptr, scale); 3107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion scaledRgnA; 3108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath scaledA; 3109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledA.addPath(path, scale); 3110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledA.setFillType(path.getFillType()); 3111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnA.setPath(scaledA, openClip); 3112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledRgnA.getBoundaryPath(&scaledPathOut); 3113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bitmap; 3114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath scaledOut; 3115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledOut.addPath(result, scale); 3116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot scaledOut.setFillType(result.getFillType()); 3117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap); 3118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int MAX_ERRORS = 9; 3119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (errors > MAX_ERRORS) { 3120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fprintf(stderr, "// Simplify did not expect errors=%d\n", errors); 3121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DumpSimplify(stderr, path, "simplifyTest"); 3122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fflush(stderr); 3123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 3124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 3125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 3126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 3127