SkPathOpsDebug.cpp revision f2b340fc885ad2a12d2d73974eff9c8f4c94192c
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 Google Inc. 307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * 407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file. 607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 81b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h" 926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpCoincidence.h" 1026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkOpContour.h" 1102802f64ea0b1fc9223386328a95280b74092c94jvanverth#include "SkPath.h" 121b24933e52f50773de29332387a12721811f3012mtklein#include "SkPathOpsDebug.h" 1354359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkString.h" 1454359294a7c9dc54802d512a5d891a35c1663392caryclark 1526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkCoincidentSpans; 1626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1754359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 1854359294a7c9dc54802d512a5d891a35c1663392caryclarkextern bool FLAGS_runFail; 1954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 21624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 22624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCountDefault = SK_MaxS32; 23624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkPathOpsDebug::gSortCount; 24624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 25624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 26624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_ACTIVE_OP 27624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkconst char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"}; 28624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 29624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if defined SK_DEBUG || !FORCE_RELEASE 3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 32570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comconst char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"}; 338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org 34fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gContourID = 0; 35fe41b8ffff3463a1b062c4fd7315b44e278ba390commit-bot@chromium.orgint SkPathOpsDebug::gSegmentID = 0; 36570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 3754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpanBase* >& chaseArray, 3854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span) { 394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < chaseArray.count(); ++index) { 4054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* entry = chaseArray[index]; 414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (entry == span) { 424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 4826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 4926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 5026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkenum GlitchType { 5126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddCorruptCoin_Glitch, 5226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddExpandedCoin_Glitch, 5326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kAddMissingCoin_Glitch, 5426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedCoin_Glitch, 5526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedDone_Glitch, 5626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedOppValue_Glitch, 5726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedSpan_Glitch, 5826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kCollapsedWindValue_Glitch, 5926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kDeletedCoin_Glitch, 6026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kExpandCoin_Glitch, 6126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinEnd_Glitch, 6226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMarkCoinInsert_Glitch, 6326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingCoin_Glitch, 6426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingDone_Glitch, 6526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMissingIntersection_Glitch, 6626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kMoveMultiple_Glitch, 6726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnaligned_Glitch, 6826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedHead_Glitch, 6926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnalignedTail_Glitch, 7026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUndetachedSpan_Glitch, 7126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark kUnmergedSpan_Glitch, 7226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 7326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 7426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic const int kGlitchType_Count = kUnmergedSpan_Glitch + 1; 7526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 7626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SpanGlitch { 7726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* fStage; 7826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fBase; 7926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* fSuspect; 8026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* fCoin; 8126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* fSegment; 8226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fCoinSpan; 8326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fEndSpan; 8426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppSpan; 8526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* fOppEndSpan; 8626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double fT; 8726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint fPt; 8826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchType fType; 8926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 9026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 9126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstruct SkPathOpsDebug::GlitchLog { 9226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* recordCommon(GlitchType type, const char* stage) { 9326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = fGlitches.push(); 9426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fStage = stage; 9526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = nullptr; 9626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = nullptr; 9726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoin = nullptr; 9826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = nullptr; 9926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = nullptr; 10026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = nullptr; 10126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = nullptr; 10226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = nullptr; 10326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fT = SK_ScalarNaN; 10426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = { SK_ScalarNaN, SK_ScalarNaN }; 10526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fType = type; 10626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return glitch; 10726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 10826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 10926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 11026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect = NULL) { 11126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 11226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 11326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 11426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 11526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 11626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 11726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan) { 11826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 11926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoin = coin; 12026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = coinSpan; 12126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 12226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 12326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, 12426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* seg, double t, SkPoint pt) { 12526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 12626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 12726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSegment = seg; 12826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fT = t; 12926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 13026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 13126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 13226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpSpanBase* base, double t, 13326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint pt) { 13426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 13526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fBase = base; 13626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fT = t; 13726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fPt = pt; 13826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 13926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 14026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 14126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinSpan, const SkOpPtT* endSpan) { 14226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 14326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoin = coin; 14426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = coinSpan; 14526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = endSpan; 14626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 14726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 14826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkCoincidentSpans* coin, 14926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* suspect) { 15026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 15126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fSuspect = suspect; 15226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoin = coin; 15326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 15426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 15526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark void record(GlitchType type, const char* stage, const SkOpPtT* ptTS, const SkOpPtT* ptTE, 15626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oPtTS, const SkOpPtT* oPtTE) { 15726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SpanGlitch* glitch = recordCommon(type, stage); 15826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fCoinSpan = ptTS; 15926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fEndSpan = ptTE; 16026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppSpan = oPtTS; 16126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitch->fOppEndSpan = oPtTE; 16226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 16326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 16426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTDArray<SpanGlitch> fGlitches; 16526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark}; 16626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 16726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { 16826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark GlitchLog glitches; 16926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* contour = contourList; 17026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence = contour->globalState()->coincidence(); 17126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 17226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark contour->debugCheckHealth(id, &glitches); 17326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark contour->debugMissingCoincidence(id, &glitches, coincidence); 17426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((contour = contour->next())); 17526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugFixAligned(id, &glitches); 17626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddMissing(id, &glitches); 17726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugExpand(id, &glitches); 17826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugAddExpanded(id, &glitches); 17926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincidence->debugMark(id, &glitches); 18026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark unsigned mask = 0; 18126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < glitches.fGlitches.count(); ++index) { 18226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SpanGlitch& glitch = glitches.fGlitches[index]; 18326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark mask |= 1 << glitch.fType; 18426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < kGlitchType_Count; ++index) { 18626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(mask & (1 << index) ? "x" : "-"); 18726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 18826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(" %s\n", id); 18926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 19026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 1914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 19226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if defined SK_DEBUG || !FORCE_RELEASE 193570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) { 19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com size_t len = strlen(str); 19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool num = false; 19607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (size_t idx = 0; idx < len; ++idx) { 19707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (num && str[idx] == 'e') { 19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (len + 2 >= bufferLen) { 19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com memmove(&str[idx + 2], &str[idx + 1], len - idx); 20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx] = '*'; 20307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com str[idx + 1] = '^'; 20407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++len; 20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com num = str[idx] >= '0' && str[idx] <= '9'; 20707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 210570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkPathOpsDebug::ValidWind(int wind) { 21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF; 21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 214570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::WindingPrintf(int wind) { 21507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (wind == SK_MinS32) { 21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("?"); 21707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%d", wind); 21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 22154359294a7c9dc54802d512a5d891a35c1663392caryclark#endif // defined SK_DEBUG || !FORCE_RELEASE 22254359294a7c9dc54802d512a5d891a35c1663392caryclark 223a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 22407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com#if DEBUG_SHOW_TEST_NAME 225385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* SkPathOpsDebug::CreateNameStr() { return new char[DEBUG_FILENAME_STRING_LENGTH]; } 226cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 227385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid SkPathOpsDebug::DeleteNameStr(void* v) { delete[] reinterpret_cast<char*>(v); } 228a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com 229570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkPathOpsDebug::BumpTestName(char* test) { 23007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com char* num = test + strlen(test); 23107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com while (num[-1] >= '0' && num[-1] <= '9') { 23207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com --num; 23307e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 23407e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (num[0] == '\0') { 23507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 23607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 23707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com int dec = atoi(num); 23807e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com if (dec == 0) { 23907e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com return; 24007e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 24107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com ++dec; 24207e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com SK_SNPRINTF(num, DEBUG_FILENAME_STRING_LENGTH - (num - test), "%d", dec); 243a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com} 244a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 245570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 2461049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_function_header(const char* functionName) { 2471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); 2481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (strcmp("skphealth_com76", functionName) == 0) { 2491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("found it\n"); 2501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 2511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 2521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 2531049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gOpStrs[] = { 2541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kDifference_SkPathOp", 2551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kIntersect_SkPathOp", 2561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kUnion_SkPathOp", 2571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kXor_PathOp", 2581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kReverseDifference_SkPathOp", 2591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 2601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 26103b03cad01628146bbb8d4f33c073bd0c77ee558caryclarkconst char* SkPathOpsDebug::OpStr(SkPathOp op) { 26203b03cad01628146bbb8d4f33c073bd0c77ee558caryclark return gOpStrs[op]; 26303b03cad01628146bbb8d4f33c073bd0c77ee558caryclark} 26403b03cad01628146bbb8d4f33c073bd0c77ee558caryclark 2651049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { 2661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); 2671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("}\n"); 2681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 2691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 2701049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkSK_DECLARE_STATIC_MUTEX(gTestMutex); 2711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 2721049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, 2731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* testName) { 2741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkAutoMutexAcquire ac(gTestMutex); 2751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_function_header(testName); 2761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(a, "path", true); 2771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ShowOnePath(b, "pathB", true); 2781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark show_op(shapeOp, "path", "pathB"); 2794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 2804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 28127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#include "SkPathOpsTypes.h" 28226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersectionHelper.h" 28326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#include "SkIntersections.h" 28426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 28526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 28626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugAddLoopCount(SkIntersections* i, const SkIntersectionHelper& wt, 28726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkIntersectionHelper& wn) { 28826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 28926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections::DebugLoop looper = (SkIntersections::DebugLoop) index; 29026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= i->debugLoopCount(looper)) { 29126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 29226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 29326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = i->debugLoopCount(looper); 29426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = wt.segment()->verb(); 29526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = wn.segment()->verb(); 29626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(&fDebugWorstPts[index * 8], sizeof(SkPoint) * 8); 29726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], wt.pts(), 29826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wt.segment()->verb()) + 1) * sizeof(SkPoint)); 29926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[(index * 2 + 1) * 4], wn.pts(), 30026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkPathOpsVerbToPoints(wn.segment()->verb()) + 1) * sizeof(SkPoint)); 30126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = wt.weight(); 30226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = wn.weight(); 30326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 30426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i->debugResetLoopCount(); 30526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 30626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 30726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugDoYourWorst(SkOpGlobalState* local) { 30826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 30926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fDebugLoopCount[index] >= local->fDebugLoopCount[index]) { 31026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 31126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 31226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index] = local->fDebugLoopCount[index]; 31326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2] = local->fDebugWorstVerb[index * 2]; 31426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstVerb[index * 2 + 1] = local->fDebugWorstVerb[index * 2 + 1]; 31526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark memcpy(&fDebugWorstPts[index * 2 * 4], &local->fDebugWorstPts[index * 2 * 4], 31626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sizeof(SkPoint) * 8); 31726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2] = local->fDebugWorstWeight[index * 2]; 31826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1] = local->fDebugWorstWeight[index * 2 + 1]; 31926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 32026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark local->debugResetLoopCounts(); 32126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 32226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 32326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void dump_curve(SkPath::Verb verb, const SkPoint& pts, float weight) { 32426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!verb) { 32526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 32626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 32726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* verbs[] = { "", "line", "quad", "conic", "cubic" }; 32826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: {{", verbs[verb]); 32926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int ptCount = SkPathOpsVerbToPoints(verb); 33026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index <= ptCount; ++index) { 33126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::Dump((&pts)[index]); 33226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (index < ptCount - 1) { 33326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 33426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 33526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 33626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}"); 33726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight != 1) { 33826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf(", "); 33926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (weight == floorf(weight)) { 34026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%.0f", weight); 34126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 34226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%1.9gf", weight); 34326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 34426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 34526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("}\n"); 34626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 34726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 34826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugLoopReport() { 34926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const char* loops[] = { "iterations", "coinChecks", "perpCalcs" }; 35026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 35126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < (int) SK_ARRAY_COUNT(fDebugLoopCount); ++index) { 35226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s: %d\n", loops[index], fDebugLoopCount[index]); 35326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2], fDebugWorstPts[index * 2 * 4], 35426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2]); 35526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark dump_curve(fDebugWorstVerb[index * 2 + 1], fDebugWorstPts[(index * 2 + 1) * 4], 35626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugWorstWeight[index * 2 + 1]); 35726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 35826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 35926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 36026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpGlobalState::debugResetLoopCounts() { 36126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 36226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstVerb, sizeof(fDebugWorstVerb)); 36326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstPts, sizeof(fDebugWorstPts)); 36426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugWorstWeight, sizeof(fDebugWorstWeight)); 36526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 36626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 36727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 36827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#ifdef SK_DEBUG 36927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpGlobalState::debugRunFail() const { 37027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#if DEBUG_VALIDATE 37127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return FLAGS_runFail; 37227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#else 37327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 37427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 37527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 37627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark#endif 37727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 37826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_T_SECT_LOOP_COUNT 37926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugBumpLoopCount(DebugLoop index) { 38026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark fDebugLoopCount[index]++; 38126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 38226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 38326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkint SkIntersections::debugLoopCount(DebugLoop index) const { 38426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return fDebugLoopCount[index]; 38526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 38626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 38726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkIntersections::debugResetLoopCount() { 38826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount)); 38926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 39026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 39126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 392624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsCubic.h" 393624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#include "SkPathOpsQuad.h" 394624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 395624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkSkDCubic SkDQuad::debugToCubic() const { 396624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDCubic cubic; 397624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[0] = fPts[0]; 398624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2] = fPts[1]; 399624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[3] = fPts[2]; 400624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; 401624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; 402624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; 403624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; 404624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return cubic; 405624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 406624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 407ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclarkvoid SkDRect::debugInit() { 408ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark fLeft = fTop = fRight = fBottom = SK_ScalarNaN; 409ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark} 410ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark 4114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#include "SkOpAngle.h" 412570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#include "SkOpSegment.h" 413570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 41426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 41526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugAddAlignIntersection(const char* id, SkPathOpsDebug::GlitchLog* log, 41626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT& endPtT, const SkPoint& oldPt, const SkOpContourHead* contourList) const { 41726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkPoint& newPt = endPtT.fPt; 41826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (newPt == oldPt) { 41926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 42026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 42126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPoint line[2] = { newPt, oldPt }; 42226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkPathOpsBounds lineBounds; 42326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark lineBounds.setBounds(line, 2); 42426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDLine aLine; 42526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark aLine.set(line); 42626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpContour* current = contourList; 42726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 42826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!SkPathOpsBounds::Intersects(current->bounds(), lineBounds)) { 42926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 43026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 43126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = current->first(); 43226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 43326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!SkPathOpsBounds::Intersects(segment->bounds(), lineBounds)) { 43426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 43526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 43626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (newPt == segment->fPts[0]) { 43726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 43826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 43926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (newPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { 44026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 44126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 44226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oldPt == segment->fPts[0]) { 44326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 44426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 44526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oldPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { 44626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 44726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 44826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (endPtT.debugContains(segment)) { 44926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 45026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 45126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkIntersections i; 45226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark switch (segment->fVerb) { 45326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark case SkPath::kLine_Verb: { 45426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDLine bLine; 45526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bLine.set(segment->fPts); 45626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i.intersect(bLine, aLine); 45726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } break; 45826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark case SkPath::kQuad_Verb: { 45926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDQuad bQuad; 46026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bQuad.set(segment->fPts); 46126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i.intersect(bQuad, aLine); 46226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } break; 46326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark case SkPath::kConic_Verb: { 46426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDConic bConic; 46526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bConic.set(segment->fPts, segment->fWeight); 46626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i.intersect(bConic, aLine); 46726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } break; 46826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark case SkPath::kCubic_Verb: { 46926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDCubic bCubic; 47026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bCubic.set(segment->fPts); 47126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark i.intersect(bCubic, aLine); 47226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } break; 47326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark default: 47426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(0); 47526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 47626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (i.used()) { 47726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(i.used() == 1); 47826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(!zero_or_one(i[0][0])); 47926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSpanBase* checkSpan = fHead.next(); 48026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!checkSpan->final()) { 48126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (checkSpan->contains(segment)) { 48226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto nextSegment; 48326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark checkSpan = checkSpan->upCast()->next(); 48526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMissingIntersection_Glitch, id, checkSpan, segment, i[0][0], newPt); 48726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 48826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark nextSegment: 48926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 49026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((segment = segment->next())); 49126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((current = current->next())); 49226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 49326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 49426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSegment::debugAddMissing(double t, const SkOpSegment* opp) const { 49526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* existing = nullptr; 49626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 49726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testT; 49826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 49926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((testT = test->ptT()->fT) >= t) { 50026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (testT == t) { 50126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark existing = test; 50226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 50326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 50426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 50526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->upCast()->next())); 50626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return !existing || !existing->debugContains(opp); 50726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 50826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 50926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugAlign(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 51026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* span = &fHead; 51126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!span->aligned()) { 51226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!span->debugAlignedEnd(0, fPts[0])) { 51326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnalignedHead_Glitch, id, span); 51426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 51626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((span = span->upCast()->next())) { 51726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (span == &fTail) { 51826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 51926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!span->aligned()) { 52126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnaligned_Glitch, id, span); 52226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!span->aligned()) { 52526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span->debugAlignedEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); 52626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 52726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->collapsed()) { 52826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = &fHead; 52926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 53026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (span->windValue()) { 53126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kCollapsedWindValue_Glitch, id, span); 53226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 53326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (span->oppValue()) { 53426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kCollapsedOppValue_Glitch, id, span); 53526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 53626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!span->done()) { 53726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kCollapsedDone_Glitch, id, span); 53826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 53926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((span = span->next()->upCastable())); 54026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 54126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 54226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 54326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 54426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 54526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckAngleCoin() const { 54626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* base = &fHead; 54726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span; 54826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 54926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* angle = base->fromAngle(); 55026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (angle && angle->fCheckCoincidence) { 55126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 55226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 55326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (base->final()) { 55426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 55526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 55626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark span = base->upCast(); 55726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle = span->toAngle(); 55826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (angle && angle->fCheckCoincidence) { 55926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark angle->debugCheckNearCoincidence(); 56026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 56126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((base = span->next())); 56226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 56326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 56426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 56526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 56626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// this mimics the order of the checks in handle coincidence 56726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 56826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveMultiples(id, glitches); 56926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugFindCollapsed(id, glitches); 57026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugMoveNearby(id, glitches); 57126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugAlign(id, glitches); 57226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark debugAddAlignIntersections(id, glitches, this->globalState()->contourHead()); 57326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 57426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 57526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 57626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugFindCollapsed(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 57726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (fHead.contains(&fTail)) { 57826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = this->head(); 57926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool missingDone = false; 58026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 58126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark missingDone |= !span->done(); 58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((span = span->next()->upCastable())); 58326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (missingDone) { 58426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kMissingDone_Glitch, id, &fHead); 58526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 58626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!fHead.debugAlignedEnd(0, fHead.pt())) { 58726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnalignedHead_Glitch, id, &fHead); 58826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!fTail.aligned()) { 59026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnalignedTail_Glitch, id, &fTail); 59126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 59326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 59426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 59526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 59654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::debugLastAngle() { 59796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* result = nullptr; 59854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 59954359294a7c9dc54802d512a5d891a35c1663392caryclark do { 60054359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->toAngle()) { 601dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!result); 60254359294a7c9dc54802d512a5d891a35c1663392caryclark result = span->toAngle(); 603dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 60454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 605dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(result); 606dac1d17027dcaa5596885a9f333979418b35001ccaryclark return result; 607dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 608dac1d17027dcaa5596885a9f333979418b35001ccaryclark 60926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 61026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, 61126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidences) const { 61226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->verb() != SkPath::kLine_Verb) { 61326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 61426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->done()) { 61626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 61726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 61826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prior = nullptr; 61926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanBase = &fHead; 62026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 62126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 62226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(ptT->span() == spanBase); 62326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((ptT = ptT->next()) != spanStopPtT) { 62426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->deleted()) { 62526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 62626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 62726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* opp = ptT->span()->segment(); 62826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// if (opp->verb() == SkPath::kLine_Verb) { 62926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// continue; 63026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// } 63126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->done()) { 63226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 63326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 63526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!opp->visited()) { 63626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 63726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 63826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase == &fHead) { 63926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 64026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* span = spanBase->upCastable(); 64226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 64326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // coincidence needs to be detected. This may not be true. 64426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (span && span->segment() != opp && span->containsCoincidence(opp)) { 64526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 64626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 64726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase->segment() != opp && spanBase->containsCoinEnd(opp)) { 64826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 64926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 65026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* priorPtT = nullptr, * priorStopPtT; 65126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find prior span containing opp segment 65226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* priorOpp = nullptr; 65326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* priorTest = spanBase->prev(); 65426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (!priorOpp && priorTest) { 65526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorStopPtT = priorPtT = priorTest->ptT(); 65626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 65726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT->deleted()) { 65826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 65926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* segment = priorPtT->span()->segment(); 66126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment == opp) { 66226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark prior = priorTest; 66326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorOpp = opp; 66426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 66526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark priorTest = priorTest->prev(); 66826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 66926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!priorOpp) { 67026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 67126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 67226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStart = prior->ptT(); 67326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppEnd = spanBase->ptT(); 67426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool swapped = priorPtT->fT > ptT->fT; 67526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 67626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 67726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppStart, oppEnd); 67826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 67926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool flipped = oppStart->fT > oppEnd->fT; 68026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool coincident = false; 68126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) { 68226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto swapBack; 68326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 68426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->verb() == SkPath::kLine_Verb) { 68526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppStart->fPt) || 68626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt)) && 68726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) || 68826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt)); 68926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 69026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coincident) { 69126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000); 69226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 69326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coincident) { 69426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMissingCoin_Glitch, id, priorPtT, ptT, oppStart, oppEnd); 69526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 69626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark swapBack: 69726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (swapped) { 69826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(priorPtT, ptT); 69926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 70026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 70126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 70226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 70326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 70426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 70526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = &fHead; 70626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 70726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int addCount = test->spanAddsCount(); 70826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(addCount >= 1); 70926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (addCount == 1) { 71026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 71126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 71226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = test->ptT(); 71326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testPtT = startPtT; 71426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 71526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppSpan = testPtT->span(); 71626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->spanAddsCount() == addCount) { 71726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 71826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 71926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSpan->deleted()) { 72026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 72126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 72226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppSpan->segment(); 72326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppSegment == this) { 72426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 72526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 72626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // find range of spans to consider merging 72726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppPrev = oppSpan; 72826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppFirst = oppSpan; 72926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPrev = oppPrev->prev())) { 73026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 73126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 73226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->spanAddsCount() == addCount) { 73426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 73526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPrev->deleted()) { 73726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 73826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 73926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppFirst = oppPrev; 74026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 74126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppNext = oppSpan; 74226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppLast = oppSpan; 74326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 74426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 74526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 74626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 74726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->spanAddsCount() == addCount) { 74826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 74926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppNext->deleted()) { 75126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oppLast = oppNext; 75426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppFirst == oppLast) { 75626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 75726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 75826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oppTest = oppFirst; 75926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 76026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == oppSpan) { 76126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 76226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 76326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if the candidate meets specific criteria: 76426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // it contains spans of segments in test's loop but not including 'this' 76526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppStartPtT = oppTest->ptT(); 76626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oppPtT = oppStartPtT; 76726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 76826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppPtTSegment = oppPtT->segment(); 76926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppPtTSegment == this) { 77026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 77126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* matchPtT = startPtT; 77326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 77426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (matchPtT->segment() == oppPtTSegment) { 77526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto foundMatch; 77626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 77726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((matchPtT = matchPtT->next()) != startPtT); 77826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto tryNextSpan; 77926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark foundMatch: // merge oppTest and oppSpan 78026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) { 78126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse 78226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(oppSpan != &oppSegment->fTail); 78326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kMoveMultiple_Glitch, id, oppTest, oppSpan); 78426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 78526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppTest); 78626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 78826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 78926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark tryNextSpan: 79026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 79126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 79226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testPtT = testPtT->next()) != startPtT); 79326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkcheckNextSpan: 79426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 79526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = test->final() ? nullptr : test->upCast()->next())); 79626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 79726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 79826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpSegment::debugMoveNearby(const char* id, SkPathOpsDebug::GlitchLog* glitches) const { 79926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* spanS = &fHead; 80026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 80126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = spanS->upCast()->next(); 80226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next; 80326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanS->contains(test)) { 80426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!test->final()) { 80526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUndetachedSpan_Glitch, id, test, spanS); 80626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else if (spanS != &fHead) { 80726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUndetachedSpan_Glitch, id, spanS, test); 80826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 80926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 81026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { // iterate through all spans associated with start 81126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startBase = spanS->ptT(); 81226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark next = test->final() ? nullptr : test->upCast()->next(); 81326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 81426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testBase = test->ptT(); 81526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 81626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (startBase == testBase) { 81726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 81826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 81926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (testBase->duplicate()) { 82026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 82126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 82226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) { 82326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (test == &this->fTail) { 82426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanS == &fHead) { 82526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kCollapsedSpan_Glitch, id, spanS); 82626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 82726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnmergedSpan_Glitch, id, &this->fTail, spanS); 82826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 82926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 83026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark glitches->record(kUnmergedSpan_Glitch, id, spanS, test); 83126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto checkNextSpan; 83226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 83426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((testBase = testBase->next()) != test->ptT()); 83526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((startBase = startBase->next()) != spanS->ptT()); 83626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark checkNextSpan: 83726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 83826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((test = next)); 83926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark spanS = spanS->upCast()->next(); 84026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (!spanS->final()); 84126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 84226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 84326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 8444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugReset() { 8451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->init(this->fPts, this->fWeight, this->contour(), this->verb()); 8464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 8474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 84854359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ACTIVE_SPANS 8494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugShowActiveSpans() const { 8504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 8514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (done()) { 8524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 8534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 8544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int lastId = -1; 8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double lastT = -1; 85654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* span = &fHead; 85754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 85854359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 8594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 8604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 8611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (lastId == this->debugID() && lastT == span->t()) { 8624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 8634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 8641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark lastId = this->debugID(); 86554359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = span->t(); 8661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", __FUNCTION__, this->debugID()); 8674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 8684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 8694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 8704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 8711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (SkPath::kConic_Verb == fVerb) { 8721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %1.9gf", fWeight); 8731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 87454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = span->ptT(); 87554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g (%1.9g,%1.9g)", ptT->fT, ptT->fPt.fX, ptT->fPt.fY); 87654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" tEnd=%1.9g", span->next()->t()); 87754359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 878624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=?"); 8794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 880624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windSum=%d", span->windSum()); 881624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 882624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() && span->oppSum() == SK_MinS32) { 883624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=?"); 884624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } else if (span->oppValue() || span->oppSum() != SK_MinS32) { 885624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppSum=%d", span->oppSum()); 886624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 887624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" windValue=%d", span->windValue()); 888624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (span->oppValue() || span->oppSum() != SK_MinS32) { 889624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf(" oppValue=%d", span->oppValue()); 8904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 89154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 89254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 8934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 8944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 8954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 89654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 89754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) { 89854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 8991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 9004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 9014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 9024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 9034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 90454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 90554359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t()); 90654359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 9074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 9084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 90954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 9104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 91154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 91254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 91354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 91454359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 91554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 91654359294a7c9dc54802d512a5d891a35c1663392caryclark } 91754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d\n", span->windValue()); 9184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 9194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 92054359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, 9214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppWinding) { 92254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& pt = span->ptT()->fPt; 9231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%s id=%d", fun, this->debugID()); 9244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY); 9254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) { 9264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY); 9274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 92854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=", 92954359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID(), pt.fX, pt.fY, span->next()->t(), winding, oppWinding); 93054359294a7c9dc54802d512a5d891a35c1663392caryclark if (winding == SK_MinS32) { 93154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 93254359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 93354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", winding); 93454359294a7c9dc54802d512a5d891a35c1663392caryclark } 93554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" newOppSum="); 93654359294a7c9dc54802d512a5d891a35c1663392caryclark if (oppWinding == SK_MinS32) { 93754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("?"); 93854359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 93954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", oppWinding); 94054359294a7c9dc54802d512a5d891a35c1663392caryclark } 94154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" oppSum="); 94254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->oppSum() == SK_MinS32) { 9434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 9444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 94554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->oppSum()); 9464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 9474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf(" windSum="); 94854359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->windSum() == SK_MinS32) { 9494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("?"); 9504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 95154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%d", span->windSum()); 9524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 95354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windValue=%d oppValue=%d\n", span->windValue(), span->oppValue()); 9544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 95554359294a7c9dc54802d512a5d891a35c1663392caryclark 9564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 9574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 95826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// loop looking for a pair of angle parts that are too close to be sorted 95926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark/* This is called after other more simple intersection and angle sorting tests have been exhausted. 96026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This should be rarely called -- the test below is thorough and time consuming. 96126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark This checks the distance between start points; the distance between 96226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark*/ 96326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_ANGLE 96426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpAngle::debugCheckNearCoincidence() const { 96526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* test = this; 96626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 96726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* testSegment = test->segment(); 96826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testStartT = test->start()->t(); 96926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testStartPt = testSegment->dPtAtT(testStartT); 97026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndT = test->end()->t(); 97126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint testEndPt = testSegment->dPtAtT(testEndT); 97226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testLenSq = testStartPt.distanceSquared(testEndPt); 97326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, testSegment->debugID()); 97426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidT = (testStartT + testEndT) / 2; 97526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpAngle* next = test; 97626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((next = next->fNext) != this) { 97726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSegment* nextSegment = next->segment(); 97826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testMidDistSq = testSegment->distSq(testMidT, next); 97926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double testEndDistSq = testSegment->distSq(testEndT, next); 98026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextStartT = next->start()->t(); 98126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT); 98226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double distSq = testStartPt.distanceSquared(nextStartPt); 98326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndT = next->end()->t(); 98426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidT = (nextStartT + nextEndT) / 2; 98526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextMidDistSq = nextSegment->distSq(nextMidT, test); 98626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextEndDistSq = nextSegment->distSq(nextEndT, test); 98726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq, 98826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testSegment->debugID(), nextSegment->debugID()); 98926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq); 99026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq); 99126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq); 99226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq); 99326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT); 99426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double nextLenSq = nextStartPt.distanceSquared(nextEndPt); 99526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq); 99626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("\n"); 99726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 99826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->fNext; 99926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (test->fNext != this); 100026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 100126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 100226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 100354359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ANGLE 100454359294a7c9dc54802d512a5d891a35c1663392caryclarkSkString SkOpAngle::debugPart() const { 100554359294a7c9dc54802d512a5d891a35c1663392caryclark SkString result; 100654359294a7c9dc54802d512a5d891a35c1663392caryclark switch (this->segment()->verb()) { 100754359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kLine_Verb: 100854359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(LINE_DEBUG_STR " id=%d", LINE_DEBUG_DATA(fCurvePart), 100954359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 101054359294a7c9dc54802d512a5d891a35c1663392caryclark break; 101154359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kQuad_Verb: 101254359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(QUAD_DEBUG_STR " id=%d", QUAD_DEBUG_DATA(fCurvePart), 101354359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 101454359294a7c9dc54802d512a5d891a35c1663392caryclark break; 10151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 10161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark result.printf(CONIC_DEBUG_STR " id=%d", 10171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark CONIC_DEBUG_DATA(fCurvePart, fCurvePart.fConic.fWeight), 10181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark this->segment()->debugID()); 10191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 102054359294a7c9dc54802d512a5d891a35c1663392caryclark case SkPath::kCubic_Verb: 102154359294a7c9dc54802d512a5d891a35c1663392caryclark result.printf(CUBIC_DEBUG_STR " id=%d", CUBIC_DEBUG_DATA(fCurvePart), 102254359294a7c9dc54802d512a5d891a35c1663392caryclark this->segment()->debugID()); 102354359294a7c9dc54802d512a5d891a35c1663392caryclark break; 102454359294a7c9dc54802d512a5d891a35c1663392caryclark default: 102554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 10261b24933e52f50773de29332387a12721811f3012mtklein } 102754359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 102854359294a7c9dc54802d512a5d891a35c1663392caryclark} 102954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 103054359294a7c9dc54802d512a5d891a35c1663392caryclark 1031624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#if DEBUG_SORT 103254359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugLoop() const { 103354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 103454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 103554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 103654359294a7c9dc54802d512a5d891a35c1663392caryclark next->dumpOne(true); 103754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 103854359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 103954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 104054359294a7c9dc54802d512a5d891a35c1663392caryclark next = first; 104154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 104254359294a7c9dc54802d512a5d891a35c1663392caryclark next->debugValidate(); 104354359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 104454359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1045ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1046ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1047ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 104854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidate() const { 104954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 105054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 105154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = this; 105254359294a7c9dc54802d512a5d891a35c1663392caryclark int wind = 0; 105354359294a7c9dc54802d512a5d891a35c1663392caryclark int opp = 0; 105454359294a7c9dc54802d512a5d891a35c1663392caryclark int lastXor = -1; 105554359294a7c9dc54802d512a5d891a35c1663392caryclark int lastOppXor = -1; 105654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 105754359294a7c9dc54802d512a5d891a35c1663392caryclark if (next->unorderable()) { 105854359294a7c9dc54802d512a5d891a35c1663392caryclark return; 105954359294a7c9dc54802d512a5d891a35c1663392caryclark } 106054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = next->start()->starter(next->end()); 106154359294a7c9dc54802d512a5d891a35c1663392caryclark if (minSpan->windValue() == SK_MinS32) { 106254359294a7c9dc54802d512a5d891a35c1663392caryclark return; 106354359294a7c9dc54802d512a5d891a35c1663392caryclark } 106454359294a7c9dc54802d512a5d891a35c1663392caryclark bool op = next->segment()->operand(); 106554359294a7c9dc54802d512a5d891a35c1663392caryclark bool isXor = next->segment()->isXor(); 106654359294a7c9dc54802d512a5d891a35c1663392caryclark bool oppXor = next->segment()->oppXor(); 106754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || between(0, minSpan->windValue(), DEBUG_LIMIT_WIND_SUM)); 106854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM 106954359294a7c9dc54802d512a5d891a35c1663392caryclark || between(-DEBUG_LIMIT_WIND_SUM, minSpan->oppValue(), DEBUG_LIMIT_WIND_SUM)); 107054359294a7c9dc54802d512a5d891a35c1663392caryclark bool useXor = op ? oppXor : isXor; 107154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastXor == -1 || lastXor == (int) useXor); 107254359294a7c9dc54802d512a5d891a35c1663392caryclark lastXor = (int) useXor; 1073624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark wind += next->debugSign() * (op ? minSpan->oppValue() : minSpan->windValue()); 107454359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 107554359294a7c9dc54802d512a5d891a35c1663392caryclark wind &= 1; 107654359294a7c9dc54802d512a5d891a35c1663392caryclark } 107754359294a7c9dc54802d512a5d891a35c1663392caryclark useXor = op ? isXor : oppXor; 107854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastOppXor == -1 || lastOppXor == (int) useXor); 107954359294a7c9dc54802d512a5d891a35c1663392caryclark lastOppXor = (int) useXor; 1080624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark opp += next->debugSign() * (op ? minSpan->windValue() : minSpan->oppValue()); 108154359294a7c9dc54802d512a5d891a35c1663392caryclark if (useXor) { 108254359294a7c9dc54802d512a5d891a35c1663392caryclark opp &= 1; 108354359294a7c9dc54802d512a5d891a35c1663392caryclark } 108454359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->fNext; 108554359294a7c9dc54802d512a5d891a35c1663392caryclark } while (next && next != first); 1086182b499cd75c971f85cdf52c1827b3c220cc9011caryclark SkASSERT(wind == 0 || !FLAGS_runFail); 108754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(opp == 0 || !FLAGS_runFail); 108854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 108954359294a7c9dc54802d512a5d891a35c1663392caryclark} 109054359294a7c9dc54802d512a5d891a35c1663392caryclark 109154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpAngle::debugValidateNext() const { 109254359294a7c9dc54802d512a5d891a35c1663392caryclark#if !FORCE_RELEASE 109354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* first = this; 109454359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpAngle* next = first; 109554359294a7c9dc54802d512a5d891a35c1663392caryclark SkTDArray<const SkOpAngle*>(angles); 109654359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1097f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen// SkASSERT_RELEASE(next->fSegment->debugContains(next)); 109854359294a7c9dc54802d512a5d891a35c1663392caryclark angles.push(next); 109954359294a7c9dc54802d512a5d891a35c1663392caryclark next = next->next(); 110054359294a7c9dc54802d512a5d891a35c1663392caryclark if (next == first) { 110154359294a7c9dc54802d512a5d891a35c1663392caryclark break; 110254359294a7c9dc54802d512a5d891a35c1663392caryclark } 1103f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SkASSERT_RELEASE(!angles.contains(next)); 110454359294a7c9dc54802d512a5d891a35c1663392caryclark if (!next) { 110554359294a7c9dc54802d512a5d891a35c1663392caryclark return; 110654359294a7c9dc54802d512a5d891a35c1663392caryclark } 110754359294a7c9dc54802d512a5d891a35c1663392caryclark } while (true); 110854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 110954359294a7c9dc54802d512a5d891a35c1663392caryclark} 111054359294a7c9dc54802d512a5d891a35c1663392caryclark 111126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 111226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 111326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* log) const { 111426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // for each coincident pair, match the spans 111526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span 111626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = this->fHead; 111726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 111826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coin = this->fTop; 111926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1120ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark if (!coin) { 1121ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark return; 1122ed0935a28a29af7d3b16ac8d9365f291a335c6bdcaryclark } 112326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 112426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* startPtT = coin->fCoinPtTStart; 112526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* oStartPtT = coin->fOppPtTStart; 112626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(startPtT->contains(oStartPtT)); 112726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd)); 112826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* start = startPtT->span(); 112926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = oStartPtT->span(); 113026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); 113126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); 113226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* test = start->upCast()->next(); 113326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->upCast()->next(); 113426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (test != end || oTest != oEnd) { 113526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool bumpTest = true; 113626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool bumpOTest = true; 113726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!test->ptT()->contains(oTest->ptT())) { 113826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // use t ranges to guess which one is missing 113926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double startRange = coin->fCoinPtTEnd->fT - startPtT->fT; 114026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double startPart = (test->t() - startPtT->fT) / startRange; 114126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT; 114226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; 114326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (startPart == oStartPart) { 114426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // data is corrupt 114526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddCorruptCoin_Glitch, id, start, oStart); 114626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 114726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 114826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (startPart < oStartPart) { 114926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double newT = oStartPtT->fT + oStartRange * startPart; 115026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddExpandedCoin_Glitch, id, oStart, newT, test->pt()); 115126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bumpOTest = false; 115226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 115326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double newT = startPtT->fT + startRange * oStartPart; 115426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddExpandedCoin_Glitch, id, start, newT, oTest->pt()); 115526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bumpTest = false; 115626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 115726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 115826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (bumpTest && test != end) { 115926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->upCast()->next(); 116026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 116126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (bumpOTest && oTest != oEnd) { 116226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next(); 116326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 116426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 116526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((coin = coin->fNext)); 116626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 116726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 116826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkstatic void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, double tEnd, 116926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs, double* coinTe) { 117026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double denom = overE->fT - overS->fT; 117126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double start = 0 < denom ? tStart : tEnd; 117226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double end = 0 < denom ? tEnd : tStart; 117326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double sRatio = (start - overS->fT) / denom; 117426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double eRatio = (end - overS->fT) / denom; 117526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; 117626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; 117726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 117826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 117926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, 118026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* over1e) const { 118126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* check = this->fTop; 118226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (check) { 118326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (check->fCoinPtTStart->span() == over1s->span() 118426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && check->fOppPtTStart->span() == outer->fOppPtTStart->span()) { 118526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(check->fCoinPtTEnd->span() == over1e->span() 118626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark || !fDebugState->debugRunFail()); 118726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span() 118826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark || !fDebugState->debugRunFail()); 118926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 119026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 119126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span() 119226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && check->fOppPtTStart->span() == over1s->span()) { 119326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(check->fCoinPtTEnd->span() == outer->fCoinPtTEnd->span() 119426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark || !fDebugState->debugRunFail()); 119526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(check->fOppPtTEnd->span() == over1e->span() 119626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark || !fDebugState->debugRunFail()); 119726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 119826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 119926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark check = check->fNext; 120026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 120126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 120226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 120326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 120426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, 120526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd, 120626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 120726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const { 120826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double coinTs, coinTe, oppTs, oppTe; 120926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe); 121026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe); 121126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* coinSeg = coinPtTStart->segment(); 121226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSeg = oppPtTStart->segment(); 121326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(coinSeg != oppSeg); 121426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* check = this->fTop; 121526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ; 121626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while (check) { 121726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* checkCoinSeg = check->fCoinPtTStart->segment(); 121826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* checkOppSeg; 121926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (checkCoinSeg != coinSeg && checkCoinSeg != oppSeg) { 122026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto next; 122126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 122226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark checkOppSeg = check->fOppPtTStart->segment(); 122326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (checkOppSeg != coinSeg && checkOppSeg != oppSeg) { 122426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark goto next; 122526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 122626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark { 122726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int cTs = coinTs; 122826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int cTe = coinTe; 122926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int oTs = oppTs; 123026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int oTe = oppTe; 123126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (checkCoinSeg != coinSeg) { 123226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(checkOppSeg != oppSeg); 123326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(cTs, oTs); 123426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(cTe, oTe); 123526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 123626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int tweenCount = (int) between(check->fCoinPtTStart->fT, cTs, check->fCoinPtTEnd->fT) 123726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark + (int) between(check->fCoinPtTStart->fT, cTe, check->fCoinPtTEnd->fT) 123826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark + (int) between(check->fOppPtTStart->fT, oTs, check->fOppPtTEnd->fT) 123926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark + (int) between(check->fOppPtTStart->fT, oTe, check->fOppPtTEnd->fT); 124026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // SkASSERT(tweenCount == 0 || tweenCount == 4); 124126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (tweenCount) { 124226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 124326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 124426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 124526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarknext: 124626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark check = check->fNext; 124726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 124826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { 124926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 125026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 125126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coinTs > coinTe) { 125226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(coinTs, coinTe); 125326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oppTs, oppTe); 125426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 125526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool cs = coinSeg->debugAddMissing(coinTs, oppSeg); 125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool ce = coinSeg->debugAddMissing(coinTe, oppSeg); 125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (cs == ce) { 125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 125926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 126026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 126126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 126226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 126326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* log) const { 126426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* outer = fHead; 126526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!outer) { 126626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 126826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 126926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing can modify the list that this is walking 127026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // save head so that walker can iterate over old data unperturbed 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // addifmissing adds to head freely then add saved head in the end 127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment(); 127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(outerCoin == outer->fCoinPtTEnd->segment()); 127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* outerOpp = outer->fOppPtTStart->segment(); 127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(outerOpp == outer->fOppPtTEnd->segment()); 127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* inner = outer; 127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((inner = inner->fNext)) { 127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double overS, overE; 127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* innerCoin = inner->fCoinPtTStart->segment(); 128026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(innerCoin == inner->fCoinPtTEnd->segment()); 128126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* innerOpp = inner->fOppPtTStart->segment(); 128226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(innerOpp == inner->fOppPtTEnd->segment()); 128326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (outerCoin == innerCoin 128426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, 128526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { 128626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd, 128726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, 128826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark outer->fOppPtTStart, outer->fOppPtTEnd, 128926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd)) { 129026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinPtTStart); 129126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 129226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else if (outerCoin == innerOpp 129326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, 129426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { 129526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd, 129626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, 129726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark outer->fOppPtTStart, outer->fOppPtTEnd, 129826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd)) { 129926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPtTStart); 130026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 130126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else if (outerOpp == innerCoin 130226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, 130326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { 130426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, 130526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, 130626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark outer->fCoinPtTStart, outer->fCoinPtTEnd, 130726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd)) { 130826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, outer, inner->fCoinPtTStart); 130926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 131026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else if (outerOpp == innerOpp 131126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, 131226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { 131326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, 131426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, 131526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark outer->fCoinPtTStart, outer->fCoinPtTEnd, 131626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark inner->fCoinPtTStart, inner->fCoinPtTEnd)) { 131726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, outer, inner->fOppPtTStart); 131826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 131926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else if (outerCoin != innerCoin) { 132026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // check to see if outer span overlaps the inner span 132126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // look for inner segment in pt-t list 132226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // if present, and if t values are in coincident range 132326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // add two pairs of new coincidence 132426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testS = outer->fCoinPtTStart->debugContains(innerCoin); 132526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* testE = outer->fCoinPtTEnd->debugContains(innerCoin); 132626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (testS && testS->fT >= inner->fCoinPtTStart->fT 132726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && testE && testE->fT <= inner->fCoinPtTEnd->fT 132826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->testForCoincidence(outer, testS, testE)) { 132926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(outer, testS, testE)) { 133026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, outer, testS, testE); 133126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 133226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 133326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testS = inner->fCoinPtTStart->debugContains(outerCoin); 133426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark testE = inner->fCoinPtTEnd->debugContains(outerCoin); 133526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (testS && testS->fT >= outer->fCoinPtTStart->fT 133626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && testE && testE->fT <= outer->fCoinPtTEnd->fT 133726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark && this->testForCoincidence(inner, testS, testE)) { 133826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (this->debugAddIfMissing(inner, testS, testE)) { 133926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kAddMissingCoin_Glitch, id, inner, testS, testE); 134026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 134126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 134226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 134326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 134426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 134526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((outer = outer->fNext)); 134626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 134726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 134826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpCoincidence::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const { 134926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 135026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 135126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 135226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 135326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool expanded = false; 135426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 135526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* start = coin->fCoinPtTStart->span()->upCast(); 135626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); 135726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = coin->fCoinPtTStart->segment(); 135826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = coin->fOppPtTStart->segment(); 135926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* prev = start->prev(); 136026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (prev && prev->debugContains(oppSegment)) { 136126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double midT = (prev->t() + start->t()) / 2; 136226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment->isClose(midT, oppSegment)) { 136326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kExpandCoin_Glitch, id, coin, prev); 136426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 136626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 136726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (next && next->debugContains(oppSegment)) { 136826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark double midT = (end->t() + next->t()) / 2; 136926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (segment->isClose(midT, oppSegment)) { 137026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kExpandCoin_Glitch, id, coin, next); 137126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 137226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 137326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((coin = coin->fNext)); 137426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return expanded; 137526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 137626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 137726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugFixAligned(const char* id, SkPathOpsDebug::GlitchLog* log) const { 137826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 137926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 138026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 138126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 138226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 138326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fCoinPtTStart->deleted()) { 138426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTStart); 138526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 138626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fCoinPtTEnd->deleted()) { 138726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kDeletedCoin_Glitch, id, coin, coin->fCoinPtTEnd); 138826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 138926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fOppPtTStart->deleted()) { 139026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTStart); 139126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 139226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fOppPtTEnd->deleted()) { 139326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kDeletedCoin_Glitch, id, coin, coin->fOppPtTEnd); 139426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 139526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((coin = coin->fNext)); 139626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coin = fHead; 139726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 139826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fCoinPtTStart->collapsed(coin->fCoinPtTEnd)) { 139926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kCollapsedCoin_Glitch, id, coin, coin->fCoinPtTStart); 140026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (coin->fOppPtTStart->collapsed(coin->fOppPtTEnd)) { 140226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kCollapsedCoin_Glitch, id, coin, coin->fOppPtTStart); 140326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 140426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((coin = coin->fNext)); 140526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 140626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 140726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log) const { 140826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkCoincidentSpans* coin = fHead; 140926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coin) { 141026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return; 141126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 141226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 141326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); 141426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oldEnd = end; 141526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* start = coin->fCoinPtTStart->span()->debugStarter(&end); 141626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); 141726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oOldEnd = oEnd; 141826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oStart = coin->fOppPtTStart->span()->debugStarter(&oEnd); 141926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool flipped = (end == oldEnd) != (oEnd == oOldEnd); 142026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (flipped) { 142126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkTSwap(oStart, oEnd); 142226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 142326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* next = start; 142426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* oNext = oStart; 142526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 142626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark next = next->upCast()->next(); 142726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark oNext = flipped ? oNext->prev() : oNext->upCast()->next(); 142826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (next == end || oNext == oEnd) { 142926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 143026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 143126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!next->containsCoinEnd(oNext)) { 143226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMarkCoinEnd_Glitch, id, next, oNext); 143326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 143426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* nextSpan = next->upCast(); 143526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpan* oNextSpan = oNext->upCast(); 143626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!nextSpan->containsCoincidence(oNextSpan)) { 143726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark log->record(kMarkCoinInsert_Glitch, id, nextSpan, oNextSpan); 143826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 143926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 144026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((coin = coin->fNext)); 144126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 144226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 144326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 1444624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpCoincidence::debugShowCoincidence() const { 1445624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkCoincidentSpans* span = fHead; 1446624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark while (span) { 1447624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 1448624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark span->fCoinPtTStart->segment()->debugID(), 1449624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark span->fCoinPtTStart->fT, span->fCoinPtTEnd->fT); 1450624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, 1451624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark span->fOppPtTStart->segment()->debugID(), 1452624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark span->fOppPtTStart->fT, span->fOppPtTEnd->fT); 1453624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark span = span->fNext; 1454624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1455624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 1456624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 145726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#if DEBUG_COINCIDENCE 145826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* log) const { 145926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 146026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 146126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark segment->debugCheckHealth(id, log); 146226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((segment = segment->next())); 146326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 146426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 146526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkvoid SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, 146626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpCoincidence* coincidence) const { 146726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = &fHead; 146826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 146926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark segment->debugMissingCoincidence(id, log, coincidence); 147026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((segment = segment->next())); 147126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 147226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark#endif 147326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 14744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::debugValidate() const { 14754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE 147654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* span = &fHead; 147754359294a7c9dc54802d512a5d891a35c1663392caryclark double lastT = -1; 147896fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpSpanBase* prev = nullptr; 147954359294a7c9dc54802d512a5d891a35c1663392caryclark int count = 0; 14804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int done = 0; 148154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 148254359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->final()) { 148354359294a7c9dc54802d512a5d891a35c1663392caryclark ++count; 148454359294a7c9dc54802d512a5d891a35c1663392caryclark done += span->upCast()->done() ? 1 : 0; 148554359294a7c9dc54802d512a5d891a35c1663392caryclark } 148654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->segment() == this); 148754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev->upCast()->next() == span); 148854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(!prev || prev == span->prev()); 148954359294a7c9dc54802d512a5d891a35c1663392caryclark prev = span; 149054359294a7c9dc54802d512a5d891a35c1663392caryclark double t = span->ptT()->fT; 149154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(lastT < t); 149254359294a7c9dc54802d512a5d891a35c1663392caryclark lastT = t; 149354359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 149454359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 149554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(count == fCount); 149654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(done == fDoneCount); 149708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(count >= fDoneCount); 149854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span->final()); 149954359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugValidate(); 150054359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 150154359294a7c9dc54802d512a5d891a35c1663392caryclark} 150254359294a7c9dc54802d512a5d891a35c1663392caryclark 150326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugAlignedEnd(double t, const SkPoint& pt) const { 150426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(zero_or_one(t)); 150526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* segment = this->segment(); 150626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(t ? segment->lastPt() == pt : segment->pts()[0] == pt); 150726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!debugAlignedInner()) { 150826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 150926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 151026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((t ? segment->lastPt() : segment->pts()[0]) != pt) { 151126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 151226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 151326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = &this->fPtT; 151426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(t == ptT->fT); 151526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(pt == ptT->fPt); 151626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = ptT, * stopPtT = ptT; 151726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((test = test->next()) != stopPtT) { 151826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* other = test->segment(); 151926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (other == this->segment()) { 152026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 152126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 152226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!zero_or_one(test->fT)) { 152326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 152426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 152526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((test->fT ? other->lastPt() : other->pts()[0]) != pt) { 152626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 152726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 152826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 152926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return this->fAligned; 153026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 153126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 153226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugAlignedInner() const { 153326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // force the spans to share points and t values 153426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT; 153526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkPoint& pt = ptT->fPt; 153626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 153726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->fPt != pt) { 153826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 153926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 154026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* span = ptT->span(); 154126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = ptT; 154226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 154326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if ((test = test->next()) == stopPtT) { 154426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark break; 154526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 154626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (span == test->span() && !span->segment()->ptsDisjoint(*ptT, *test)) { 154726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 154826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 154926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 155026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while ((ptT = ptT->next()) != stopPtT); 155126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 155226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 155326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 155454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::debugCoinEndLoopCheck() const { 155554359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 155654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* next = this; 155754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* nextCoin; 155854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 155954359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoinEnd; 156054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoinEnd != nextCoin); 156154359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 156254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* checkCoin = this->fCoinEnd; 156354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* innerCoin = checkCoin; 156454359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 156554359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoinEnd; 156654359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 156754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident end loop ***\n"); 156854359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 156954359294a7c9dc54802d512a5d891a35c1663392caryclark } 157054359294a7c9dc54802d512a5d891a35c1663392caryclark } 157154359294a7c9dc54802d512a5d891a35c1663392caryclark } 157254359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 157354359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 157454359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 157554359294a7c9dc54802d512a5d891a35c1663392caryclark} 157654359294a7c9dc54802d512a5d891a35c1663392caryclark 157726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpSpanBase::debugContains(const SkOpSegment* segment) const { 157826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* start = &fPtT; 157926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* walk = start; 158026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark while ((walk = walk->next()) != start) { 158126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (walk->segment() == segment) { 158226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 158326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 158426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 158526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 158626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 158726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 158826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { 158926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* end = *endPtr; 159026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() == end->segment()); 159126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSpanBase* result; 159226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (t() < end->t()) { 159326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = this; 159426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } else { 159526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark result = end; 159626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark *endPtr = this; 159726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 159826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return result->upCast(); 159926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 160026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 160154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::debugValidate() const { 160254359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 160354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* ptT = &fPtT; 160454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(ptT->span() == this); 160554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 160654359294a7c9dc54802d512a5d891a35c1663392caryclark// SkASSERT(SkDPoint::RoughlyEqual(fPtT.fPt, ptT->fPt)); 160754359294a7c9dc54802d512a5d891a35c1663392caryclark ptT->debugValidate(); 160854359294a7c9dc54802d512a5d891a35c1663392caryclark ptT = ptT->next(); 160954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (ptT != &fPtT); 161054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->debugCoinEndLoopCheck()); 161154359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final()) { 161254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this->upCast()->debugCoinLoopCheck()); 161354359294a7c9dc54802d512a5d891a35c1663392caryclark } 161454359294a7c9dc54802d512a5d891a35c1663392caryclark if (fFromAngle) { 161554359294a7c9dc54802d512a5d891a35c1663392caryclark fFromAngle->debugValidate(); 161654359294a7c9dc54802d512a5d891a35c1663392caryclark } 161754359294a7c9dc54802d512a5d891a35c1663392caryclark if (!this->final() && this->upCast()->toAngle()) { 161854359294a7c9dc54802d512a5d891a35c1663392caryclark this->upCast()->toAngle()->debugValidate(); 161954359294a7c9dc54802d512a5d891a35c1663392caryclark } 16204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 162154359294a7c9dc54802d512a5d891a35c1663392caryclark} 162254359294a7c9dc54802d512a5d891a35c1663392caryclark 162354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::debugCoinLoopCheck() const { 162454359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 162554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* next = this; 162654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* nextCoin; 162754359294a7c9dc54802d512a5d891a35c1663392caryclark do { 162854359294a7c9dc54802d512a5d891a35c1663392caryclark nextCoin = next->fCoincident; 162954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(nextCoin == this || nextCoin->fCoincident != nextCoin); 163054359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 163154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* checkCoin = this->fCoincident; 163254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* innerCoin = checkCoin; 163354359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 163454359294a7c9dc54802d512a5d891a35c1663392caryclark innerCoin = innerCoin->fCoincident; 163554359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkCoin == innerCoin) { 163654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad coincident loop ***\n"); 163754359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 163854359294a7c9dc54802d512a5d891a35c1663392caryclark } 163954359294a7c9dc54802d512a5d891a35c1663392caryclark } 164054359294a7c9dc54802d512a5d891a35c1663392caryclark } 164154359294a7c9dc54802d512a5d891a35c1663392caryclark ++loop; 164254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = nextCoin) && next != this); 164354359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 164454359294a7c9dc54802d512a5d891a35c1663392caryclark} 164554359294a7c9dc54802d512a5d891a35c1663392caryclark 1646624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark// called only by test code 1647624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkIntersections::debugCoincidentUsed() const { 1648624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (!fIsCoincident[0]) { 1649624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(!fIsCoincident[1]); 1650624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return 0; 1651624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1652624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark int count = 0; 1653624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkDEBUGCODE(int count2 = 0;) 1654624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark for (int index = 0; index < fUsed; ++index) { 1655624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[0] & (1 << index)) { 1656624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count; 1657624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1658624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#ifdef SK_DEBUG 1659624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (fIsCoincident[1] & (1 << index)) { 1660624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark ++count2; 1661624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1662624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark#endif 1663624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1664624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkASSERT(count == count2); 1665624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark return count; 1666624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark} 1667624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark 166854359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h" 166954359294a7c9dc54802d512a5d891a35c1663392caryclark 167026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkbool SkOpPtT::debugContains(const SkOpPtT* check) const { 167126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this != check); 167226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 167326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 167426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 167526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 167626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == check) { 167726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return true; 167826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 167926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 168026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 168126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 168226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 168326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return false; 168426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 168626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 168726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 168826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 168926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 169026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkconst SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const { 169126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkASSERT(this->segment() != check); 169226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* ptT = this; 169326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark int links = 0; 169426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark do { 169526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ptT = ptT->next(); 169626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT->segment() == check) { 169726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return ptT; 169826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 169926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark ++links; 170026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpPtT* test = this; 170126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark for (int index = 0; index < links; ++index) { 170226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (ptT == test) { 170326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return nullptr; 170426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark test = test->next(); 170626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 170726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } while (true); 170826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark} 170926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark 171054359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpPtT::debugLoopLimit(bool report) const { 171154359294a7c9dc54802d512a5d891a35c1663392caryclark int loop = 0; 171254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* next = this; 171354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 171454359294a7c9dc54802d512a5d891a35c1663392caryclark for (int check = 1; check < loop - 1; ++check) { 171554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* checkPtT = this->fNext; 171654359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT* innerPtT = checkPtT; 171754359294a7c9dc54802d512a5d891a35c1663392caryclark for (int inner = check + 1; inner < loop; ++inner) { 171854359294a7c9dc54802d512a5d891a35c1663392caryclark innerPtT = innerPtT->fNext; 171954359294a7c9dc54802d512a5d891a35c1663392caryclark if (checkPtT == innerPtT) { 172054359294a7c9dc54802d512a5d891a35c1663392caryclark if (report) { 172154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("*** bad ptT loop ***\n"); 172254359294a7c9dc54802d512a5d891a35c1663392caryclark } 172354359294a7c9dc54802d512a5d891a35c1663392caryclark return loop; 172454359294a7c9dc54802d512a5d891a35c1663392caryclark } 17254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 17264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 172726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // there's nothing wrong with extremely large loop counts -- but this may appear to hang 172826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // by taking a very long time to figure out that no loop entry is a duplicate 172926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark // -- and it's likely that a large loop count is indicative of a bug somewhere 173026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (++loop > 1000) { 173126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDebugf("*** loop count exceeds 1000 ***\n"); 173226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark return 1000; 173326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 173454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((next = next->fNext) && next != this); 173554359294a7c9dc54802d512a5d891a35c1663392caryclark return 0; 173654359294a7c9dc54802d512a5d891a35c1663392caryclark} 173754359294a7c9dc54802d512a5d891a35c1663392caryclark 173854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::debugValidate() const { 173954359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_VALIDATE 17404e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark SkOpGlobalState::Phase phase = contour()->globalState()->phase(); 17414e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark if (phase == SkOpGlobalState::kIntersecting 17424e1a4c9399b8bb0897218f3ec10c254d3bb97463caryclark || phase == SkOpGlobalState::kFixWinding) { 174354359294a7c9dc54802d512a5d891a35c1663392caryclark return; 17444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 174554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext); 174654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext != this); 174754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(fNext->fNext); 174854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(debugLoopLimit(false) == 0); 17494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 17504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 17511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 17521049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_scalar(SkScalar num) { 17531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (num == (int) num) { 17541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%d", (int) num); 17551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else { 17561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkString str; 17571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.printf("%1.9g", num); 17581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark int width = (int) str.size(); 17591049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const char* cStr = str.c_str(); 17601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while (cStr[width - 1] == '0') { 17611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark --width; 17621049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 17631049f1246e7be4ccb68001361efceb8933e6f81ccaryclark str.resize(width); 17641049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("%sf", str.c_str()); 17651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 17661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 17671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 17681049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void output_points(const SkPoint* pts, int count) { 17691049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int index = 0; index < count; ++index) { 17701049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fX); 17711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 17721049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_scalar(pts[index].fY); 17731049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (index + 1 < count) { 17741049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", "); 17751049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 17761049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 17771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 17781049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 17791049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void showPathContours(SkPath::RawIter& iter, const char* pathName) { 17801049f1246e7be4ccb68001361efceb8933e6f81ccaryclark uint8_t verb; 17811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPoint pts[4]; 17821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 17831049f1246e7be4ccb68001361efceb8933e6f81ccaryclark switch (verb) { 17841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kMove_Verb: 17851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.moveTo(", pathName); 17861049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[0], 1); 17871049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 17881049f1246e7be4ccb68001361efceb8933e6f81ccaryclark continue; 17891049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kLine_Verb: 17901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.lineTo(", pathName); 17911049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 1); 17921049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 17931049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 17941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kQuad_Verb: 17951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.quadTo(", pathName); 17961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 17971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 17981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 17991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kConic_Verb: 18001049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.conicTo(", pathName); 18011049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 2); 18021049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(", %1.9gf);\n", iter.conicWeight()); 18031049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 18041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kCubic_Verb: 18051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.cubicTo(", pathName); 18061049f1246e7be4ccb68001361efceb8933e6f81ccaryclark output_points(&pts[1], 3); 18071049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(");\n"); 18081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 18091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark case SkPath::kClose_Verb: 18101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.close();\n", pathName); 18111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark break; 18121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark default: 18131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGFAIL("bad verb"); 18141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 18151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 18161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 18171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 18181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 18191049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic const char* gFillTypeStr[] = { 18201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kWinding_FillType", 18211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kEvenOdd_FillType", 18221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseWinding_FillType", 18231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark "kInverseEvenOdd_FillType" 18241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}; 18251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark 18261049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { 18271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::RawIter iter(path); 18281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#define SUPPORT_RECT_CONTOUR_DETECTION 0 18291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if SUPPORT_RECT_CONTOUR_DETECTION 183096fcdcc219d2a0d3579719b84b28bede76efba64halcanary int rectCount = path.isRectContours() ? path.rectContours(nullptr, nullptr) : 0; 18311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (rectCount > 0) { 18321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkRect> rects; 18331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkTDArray<SkPath::Direction> directions; 18341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rects.setCount(rectCount); 18351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark directions.setCount(rectCount); 18361049f1246e7be4ccb68001361efceb8933e6f81ccaryclark path.rectContours(rects.begin(), directions.begin()); 18371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark for (int contour = 0; contour < rectCount; ++contour) { 18381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkRect& rect = rects[contour]; 18391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop, 18401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction 18411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction"); 18421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 18431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return; 18441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 18451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif 18461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkPath::FillType fillType = path.getFillType(); 18471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); 18481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (includeDeclaration) { 18491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" SkPath %s;\n", name); 18501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 18511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); 18521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark iter.setPath(path); 18531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark showPathContours(iter, name); 18541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark} 1855