SkOpSegment.cpp revision ccec0f958ffc71a9986d236bc2eb335cb2111119
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 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 */ 7ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#include "SkOpCoincidence.h" 8dac1d17027dcaa5596885a9f333979418b35001ccaryclark#include "SkOpContour.h" 907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h" 1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h" 11ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 12ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark/* 13ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkAfter computing raw intersections, post process all segments to: 14ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark- find small collections of points that can be collapsed to a single point 15ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark- find missing intersections to resolve differences caused by different algorithms 16ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 17ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkConsider segments containing tiny or small intervals. Consider coincident segments 18ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbecause coincidence finds intersections through distance measurement that non-coincident 19ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkintersection tests cannot. 20ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark */ 2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define F (false) // discard the edge 2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define T (true) // keep the edge 2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gUnaryActiveEdge[2][2] = { 2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// from=0 from=1 2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// to=0,1 to=0,1 2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {F, T}, {T, F}, 2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}; 3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = { 3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// miFrom=0 miFrom=1 334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// miTo=0 miTo=1 miTo=0 miTo=1 344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1 3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su 3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su 3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su 3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su 4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}; 4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef F 4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef T 4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 45ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr, 46ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** endPtr, bool* done, bool* sortable) { 47ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done, sortable)) { 484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return result; 4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 50ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done, sortable)) { 51ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return result; 5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; 5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 56ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr, 57ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** endPtr, bool* done, bool* sortable) { 58ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* upSpan = start->upCastable(); 59ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (upSpan) { 60ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (upSpan->windValue() || upSpan->oppValue()) { 61ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* next = upSpan->next(); 62ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!*endPtr) { 63ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *startPtr = start; 64ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *endPtr = next; 6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 66ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!upSpan->done()) { 67ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (upSpan->windSum() != SK_MinS32) { 68ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return spanToAngle(start, next); 694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 73ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(upSpan->done()); 7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 76ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* downSpan = start->prev(); 7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // edge leading into junction 78ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (downSpan) { 79ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (downSpan->windValue() || downSpan->oppValue()) { 80ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!*endPtr) { 81ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *startPtr = start; 82ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *endPtr = downSpan; 83ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 84ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!downSpan->done()) { 85ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (downSpan->windSum() != SK_MinS32) { 86ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return spanToAngle(start, downSpan); 874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 91ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(downSpan->done()); 9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; 954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 97ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr, 98ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** endPtr, bool* done, bool* sortable) { 99ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* oPtT = start->ptT()->next(); 100ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = oPtT->segment(); 101ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* oSpan = oPtT->span(); 102ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); 10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 105ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { 10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!done()); 10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; 10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // see if either end is not done since we want smaller Y of the pair 10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool lastDone = true; 11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double lastT = -1; 111ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* span = &fHead; 112ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 113ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (lastDone && (span->final() || span->upCast()->done())) { 11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com goto next; 11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com { 117ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkPoint& xy = span->pt(); 11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { 11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com topPt = xy; 120ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (firstSpan) { 121ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *firstSpan = span; 12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb != SkPath::kLine_Verb && !lastDone) { 125ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPts, lastT, 126ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->t()); 12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY 12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com && topPt.fX > curveTop.fX)) { 12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com topPt = curveTop; 130ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (firstSpan) { 131ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *firstSpan = span; 13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 135ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark lastT = span->t(); 13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comnext: 138ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->final()) { 139ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 140ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 141ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark lastDone = span->upCast()->done(); 142ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((span = span->upCast()->next())); 14307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return topPt; 14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 146ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask, 147ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathOp op) { 148ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumMiWinding = this->updateWinding(end, start); 149ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumSuWinding = this->updateOppWinding(end, start); 15065f553182ab7069378ef863d30094d0327f178d0caryclark#if DEBUG_LIMIT_WIND_SUM 15165f553182ab7069378ef863d30094d0327f178d0caryclark SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); 15265f553182ab7069378ef863d30094d0327f178d0caryclark SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); 15365f553182ab7069378ef863d30094d0327f178d0caryclark#endif 154ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->operand()) { 15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 157ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding); 15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 160ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, 161ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathOp op, int* sumMiWinding, int* sumSuWinding) { 1624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 163ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark this->setUpWindings(start, end, sumMiWinding, sumSuWinding, 1644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miFrom; 16607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miTo; 16707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suFrom; 16807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suTo; 16907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 1704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (oppMaxWinding & xorMiMask) != 0; 1714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (oppSumWinding & xorMiMask) != 0; 1724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (maxWinding & xorSuMask) != 0; 1734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (sumWinding & xorSuMask) != 0; 17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 1754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (maxWinding & xorMiMask) != 0; 1764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (sumWinding & xorMiMask) != 0; 1774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (oppMaxWinding & xorSuMask) != 0; 1784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (oppSumWinding & xorSuMask) != 0; 17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 18007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 18107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ACTIVE_OP 182dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", 183ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark __FUNCTION__, debugID(), start->t(), end->t(), 184570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 18507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 189ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end) { 190ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumWinding = updateWinding(end, start); 191ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return activeWinding(start, end, &sumWinding); 19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 194ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding) { 1954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding; 196ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark setUpWinding(start, end, &maxWinding, sumWinding); 1974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool from = maxWinding != 0; 19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool to = *sumWinding != 0; 19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gUnaryActiveEdge[from][to]; 20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 203ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, 204ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathWriter* path, bool active) const { 20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint edge[4]; 20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkPoint* ePtr; 207ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if ((start == &fHead && end == &fTail) || (start == &fTail && end == &fHead)) { 20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ePtr = fPts; 20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZE? if not active, skip remainder and return xyAtT(end) 21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com subDivide(start, end, edge); 21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ePtr = edge; 21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (active) { 215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool reverse = ePtr == fPts && start != &fHead; 21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (reverse) { 217277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]); 21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com switch (fVerb) { 21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kLine_Verb: 22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredLine(ePtr[0]); 22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kQuad_Verb: 22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->quadTo(ePtr[1], ePtr[0]); 22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kCubic_Verb: 22607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->cubicTo(ePtr[2], ePtr[1], ePtr[0]); 22707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 22807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com default: 22907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(0); 23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 23207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredMoveLine(ePtr[0]); 23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com switch (fVerb) { 23407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kLine_Verb: 23507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredLine(ePtr[1]); 23607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 23707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kQuad_Verb: 23807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->quadTo(ePtr[1], ePtr[2]); 23907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kCubic_Verb: 24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); 24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com default: 24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(0); 24507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 250ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* allocator) { 251ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* existing = NULL; 252ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* test = &fHead; 253ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double testT; 2544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 255ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if ((testT = test->ptT()->fT) >= t) { 256ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (testT == t) { 257ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark existing = test; 258ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 259ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 260ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 261ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((test = test->upCast()->next())); 262ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* result; 263ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (existing && existing->contains(opp)) { 264ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark result = existing->ptT(); 265ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else { 266ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark result = this->addT(t, SkOpSegment::kNoAlias, allocator); 26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 268ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(result); 269ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return result; 27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 272ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** anglePtr, 273ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkChunkAlloc* allocator) { 274ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* startSpan = fTail.prev(); 275ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(startSpan); 276ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 277ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *anglePtr = angle; 278ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle->set(&fTail, startSpan); 279ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fTail.setFromAngle(angle); 280ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = NULL; // these initializations silence a release build warning 281ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* oStartSpan = NULL; 282ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* oEndSpan = NULL; 283ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* ptT = fTail.ptT(), * startPtT = ptT; 284ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((ptT = ptT->next()) != startPtT) { 285ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark other = ptT->segment(); 286ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oStartSpan = ptT->span()->upCastable(); 287ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oStartSpan && oStartSpan->windValue()) { 288ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oEndSpan = oStartSpan->next(); 2894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 2904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 291ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oEndSpan = ptT->span(); 292ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oStartSpan = oEndSpan->prev(); 293ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oStartSpan && oStartSpan->windValue()) { 2944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 2954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 296ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 297ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 298ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oAngle->set(oStartSpan, oEndSpan); 299ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oStartSpan->setToAngle(oAngle); 3004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *otherPtr = other; 301ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return oAngle; 3024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 3034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 304ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngles(int step, SkChunkAlloc* allocator) { 3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other; 306dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle, * otherAngle; 3074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (step > 0) { 308ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark otherAngle = addSingletonAngleUp(&other, &angle, allocator); 3094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 310ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark otherAngle = addSingletonAngleDown(&other, &angle, allocator); 3114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 312dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle->insert(otherAngle); 313dac1d17027dcaa5596885a9f333979418b35001ccaryclark return angle; 3144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 3154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 316ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr, 317ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkChunkAlloc* allocator) { 318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* endSpan = fHead.next(); 319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endSpan); 320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *anglePtr = angle; 322ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle->set(&fHead, endSpan); 323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fHead.setToAngle(angle); 324ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = NULL; // these initializations silence a release build warning 325ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* oStartSpan = NULL; 326ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* oEndSpan = NULL; 327ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* ptT = fHead.ptT(), * startPtT = ptT; 328ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((ptT = ptT->next()) != startPtT) { 329ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark other = ptT->segment(); 330ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oEndSpan = ptT->span(); 331ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oStartSpan = oEndSpan->prev(); 332ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oStartSpan && oStartSpan->windValue()) { 333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 334ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 335ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oStartSpan = oEndSpan->upCastable(); 336ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oStartSpan && oStartSpan->windValue()) { 337ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oEndSpan = oStartSpan->next(); 338ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 339ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 340ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 341ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 342ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oAngle->set(oEndSpan, oStartSpan); 343ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oEndSpan->setFromAngle(oAngle); 344ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *otherPtr = other; 345ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return oAngle; 3464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 3474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 348ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpPtT* SkOpSegment::addT(double t, AllowAlias allowAlias, SkChunkAlloc* allocator) { 349ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 350ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint pt = this->ptAtT(t); 351ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* span = &fHead; 3524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 353ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* result = span->ptT(); 354ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (t == result->fT) { 355ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return result; 356ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 357ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->match(result, this, t, pt)) { 358ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // see if any existing alias matches segment, pt, and t 359ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* loop = result->next(); 360ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool duplicatePt = false; 361ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while (loop != result) { 362ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool ptMatch = loop->fPt == pt; 363ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (loop->segment() == this && loop->fT == t && ptMatch) { 364ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return result; 365ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 366ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark duplicatePt |= ptMatch; 367ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark loop = loop->next(); 368ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 369ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (kNoAlias == allowAlias) { 370ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return result; 371ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 372ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator); 373ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark alias->init(result->span(), t, pt, duplicatePt); 374ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark result->insert(alias); 375ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark result->span()->unaligned(); 376ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark this->debugValidate(); 377ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_ADD_T 378ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 379ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark alias->segment()->debugID(), alias->span()->debugID()); 380ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 381ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return alias; 382ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 383ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (t < result->fT) { 384ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* prev = result->span()->prev(); 385ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* span = insert(prev, allocator); 386ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->init(this, prev, t, pt); 387ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark this->debugValidate(); 388ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_ADD_T 389ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 390ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->segment()->debugID(), span->debugID()); 391ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 392ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return span->ptT(); 393ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 394ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(span != &fTail); 395ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((span = span->upCast()->next())); 396ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(0); 397ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 3984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 3994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 400ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// choose a solitary t and pt value; remove aliases; align the opposite ends 401ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::align() { 402ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 403ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* span = &fHead; 404ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!span->aligned()) { 405ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->alignEnd(0, fPts[0]); 406ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 407ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((span = span->upCast()->next())) { 408ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span == &fTail) { 40907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 41007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 411ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->align(); 41207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 413ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!span->aligned()) { 414ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); 41507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 416ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 417ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 418ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 419ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::BetweenTs(const SkOpSpanBase* lesser, double testT, 420ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* greater) { 421ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (lesser->t() > greater->t()) { 422ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap<const SkOpSpanBase*>(lesser, greater); 423dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 424ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return approximately_between(lesser->t(), testT, greater->t()); 42565f553182ab7069378ef863d30094d0327f178d0caryclark} 42665f553182ab7069378ef863d30094d0327f178d0caryclark 427ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::calcAngles(SkChunkAlloc* allocator) { 428ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool activePrior = !fHead.isCanceled(); 429ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (activePrior && !fHead.simple()) { 430ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark addStartSpan(allocator); 43107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 432ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* prior = &fHead; 433ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* spanBase = fHead.next(); 434ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while (spanBase != &fTail) { 435ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (activePrior) { 436ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* priorAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 437ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark priorAngle->set(spanBase, prior); 438ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanBase->setFromAngle(priorAngle); 43907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 440ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* span = spanBase->upCast(); 441ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool active = !span->isCanceled(); 442ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* next = span->next(); 443ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (active) { 444ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 445ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle->set(span, next); 446ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setToAngle(angle); 447ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 448ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark activePrior = active; 449ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark prior = span; 450ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanBase = next; 4514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 452ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (activePrior && !fTail.simple()) { 453ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark addEndSpan(allocator); 4544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 45565f553182ab7069378ef863d30094d0327f178d0caryclark} 45665f553182ab7069378ef863d30094d0327f178d0caryclark 457ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) { 458ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* base = &fHead; 459ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* span; 46065f553182ab7069378ef863d30094d0327f178d0caryclark do { 461ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = base->fromAngle(); 462ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (angle && angle->fCheckCoincidence) { 463ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle->checkNearCoincidence(); 46465f553182ab7069378ef863d30094d0327f178d0caryclark } 465ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (base->final()) { 466ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 46765f553182ab7069378ef863d30094d0327f178d0caryclark } 468ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span = base->upCast(); 469ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle = span->toAngle(); 470ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (angle && angle->fCheckCoincidence) { 471ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark angle->checkNearCoincidence(); 47265f553182ab7069378ef863d30094d0327f178d0caryclark } 473ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((base = span->next())); 47407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 47507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 476ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order 477ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swap) const { 478ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(fVerb != SkPath::kLine_Verb); 479ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint edge[4]; 480ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (fVerb == SkPath::kCubic_Verb) { 481ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double startT = start->t(); 482ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double endT = end->t(); 483ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool flip = startT > endT; 484ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDCubic cubic; 485ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark cubic.set(fPts); 486ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double inflectionTs[2]; 487ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int inflections = cubic.findInflections(inflectionTs); 488ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < inflections; ++index) { 489ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double inflectionT = inflectionTs[index]; 490ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (between(startT, inflectionT, endT)) { 491ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (flip) { 492ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (inflectionT != endT) { 493ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark startT = inflectionT; 494ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 495a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } else { 496ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (inflectionT != startT) { 497ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark endT = inflectionT; 498ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 499a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 500dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 501dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 502ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDCubic part = cubic.subDivide(startT, endT); 503ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < 4; ++index) { 504ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark edge[index] = part[index].asSkPoint(); 505ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 506ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else { 507ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark subDivide(start, end, edge); 508dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 509ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool sumSet = false; 510ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int points = SkPathOpsVerbToPoints(fVerb); 511ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY); 512ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!sumSet) { 513ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int idx = 0; idx < points; ++idx){ 514ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY); 51507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 51607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 517ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (fVerb == SkPath::kCubic_Verb) { 518ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDCubic cubic; 519ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark cubic.set(edge); 520ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *swap = sum > 0 && !cubic.monotonicInY(); 521ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else { 522ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDQuad quad; 523ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark quad.set(edge); 524ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *swap = sum > 0 && !quad.monotonicInY(); 52507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 526ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return sum <= 0; 52707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 52807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 529ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 530ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle::IncludeType includeType) { 531ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSegment* baseSegment = baseAngle->segment(); 532ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 533ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumSuWinding; 534ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool binary = includeType >= SkOpAngle::kBinarySingle; 535ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (binary) { 536ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); 537ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (baseSegment->operand()) { 538ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap<int>(sumMiWinding, sumSuWinding); 53919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } 540ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 541ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* nextSegment = nextAngle->segment(); 542ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int maxWinding, sumWinding; 543ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last; 544ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (binary) { 545ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppMaxWinding, oppSumWinding; 546ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 547ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 548ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 549ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextAngle); 5504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 551ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 552ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark &maxWinding, &sumWinding); 553ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 5544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 555ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextAngle->setLastMarked(last); 5564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 558ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 559ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle::IncludeType includeType) { 560ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSegment* baseSegment = baseAngle->segment(); 561ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumMiWinding = baseSegment->updateWinding(baseAngle); 562ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumSuWinding; 563ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool binary = includeType >= SkOpAngle::kBinarySingle; 564570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 565ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark sumSuWinding = baseSegment->updateOppWinding(baseAngle); 566ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (baseSegment->operand()) { 567ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap<int>(sumMiWinding, sumSuWinding); 568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 5694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 570ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* nextSegment = nextAngle->segment(); 571ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int maxWinding, sumWinding; 572ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last; 573ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (binary) { 574ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppMaxWinding, oppSumWinding; 575ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 576ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 578ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextAngle); 5794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 580ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 581ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark &maxWinding, &sumWinding); 582ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 583570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 584ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextAngle->setLastMarked(last); 5854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 587dac1d17027dcaa5596885a9f333979418b35001ccaryclark// at this point, the span is already ordered, or unorderable 588ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end, 589ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle::IncludeType includeType) { 5904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(includeType != SkOpAngle::kUnaryXor); 591ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* firstAngle = this->spanToAngle(end, start); 59265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (NULL == firstAngle || NULL == firstAngle->next()) { 5934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return SK_NaN32; 594570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 595570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // if all angles have a computed winding, 596570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if no adjacent angles are orderable, 597570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if adjacent orderable angles have no computed winding, 598570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // there's nothing to do 599dac1d17027dcaa5596885a9f333979418b35001ccaryclark // if two orderable angles are adjacent, and both are next to orderable angles, 600dac1d17027dcaa5596885a9f333979418b35001ccaryclark // and one has winding computed, transfer to the other 6014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* baseAngle = NULL; 602570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool tryReverse = false; 603570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // look for counterclockwise transfers 604dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle = firstAngle->previous(); 605dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* next = angle->next(); 606dac1d17027dcaa5596885a9f333979418b35001ccaryclark firstAngle = next; 60707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 608dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = angle; 609dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = next; 610dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 611dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 612dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(angle->next() == next); 613dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 614dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = NULL; 6154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 6164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 617ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int testWinding = angle->starter()->windSum(); 618dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (SK_MinS32 != testWinding) { 619dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = angle; 6204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 6214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 6224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (baseAngle) { 6244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSum(baseAngle, angle, includeType); 625ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : NULL; 6264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 627dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (next != firstAngle); 628ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) { 6294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle = baseAngle; 6304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 6314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (tryReverse) { 6334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = NULL; 634dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = firstAngle; 635570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 636dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = prior; 637dac1d17027dcaa5596885a9f333979418b35001ccaryclark prior = angle->previous(); 638dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 639dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 640dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 641dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = NULL; 642dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 643dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 644ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int testWinding = angle->starter()->windSum(); 6454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (SK_MinS32 != testWinding) { 6464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = angle; 647570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 64807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 649570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (baseAngle) { 6504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSumReverse(baseAngle, angle, includeType); 651ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : NULL; 652570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 653dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (prior != firstAngle); 654570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 655ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return start->starter(end)->windSum(); 65607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 65707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 658ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpan* SkOpSegment::crossedSpanY(const SkPoint& basePt, double mid, bool opp, bool current, 659ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkScalar* bestY, double* hitT, bool* hitSomething, bool* vertical) { 66007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar bottom = fBounds.fBottom; 661ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *vertical = false; 66207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (bottom <= *bestY) { 663ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 66407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 66507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar top = fBounds.fTop; 66607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (top >= basePt.fY) { 667ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 66807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 66907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fLeft > basePt.fX) { 670ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 67107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 67207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fRight < basePt.fX) { 673ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 67407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 67507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fLeft == fBounds.fRight) { 676ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // if vertical, and directly above test point, wait for another one 677ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *vertical = AlmostEqualUlps(basePt.fX, fBounds.fLeft); 678ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 6794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 680ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // intersect ray starting at basePt with edge 681ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkIntersections intersections; 682ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // OPTIMIZE: use specialty function that intersects ray with curve, 683ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // returning t values only for curve (we don't care about t on ray) 684ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark intersections.allowNear(false); 685ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)]) 686ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (fPts, top, bottom, basePt.fX, false); 687ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (pts == 0 || (current && pts == 1)) { 688ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 6894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 690ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (current) { 691ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(pts > 1); 692ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int closestIdx = 0; 693ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double closest = fabs(intersections[0][0] - mid); 694ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int idx = 1; idx < pts; ++idx) { 695ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double test = fabs(intersections[0][idx] - mid); 696ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (closest > test) { 697ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark closestIdx = idx; 698ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark closest = test; 6994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 7004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 701ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark intersections.quickRemoveOne(closestIdx, --pts); 7024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 703ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double bestT = -1; 704ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < pts; ++index) { 705ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double foundT = intersections[0][index]; 706ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (approximately_less_than_zero(foundT) 707ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark || approximately_greater_than_one(foundT)) { 708570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 709570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 710ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkScalar testY = (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fY; 711ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (approximately_negative(testY - *bestY) 712ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark || approximately_negative(basePt.fY - testY)) { 713570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 714570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 715ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (pts > 1 && fVerb == SkPath::kLine_Verb) { 716ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *vertical = true; 717ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; // if the intersection is edge on, wait for another one 718ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 719ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (fVerb > SkPath::kLine_Verb) { 720ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fX; 721ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (approximately_zero(dx)) { 722ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *vertical = true; 723ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; // hit vertical, wait for another one 724570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 725570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 726ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *bestY = testY; 727ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bestT = foundT; 728570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 729ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (bestT < 0) { 730ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 731570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 732ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(bestT >= 0); 733ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(bestT < 1); 734ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* testTSpanBase = &this->fHead; 735ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* nextTSpan; 736ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double endT = 0; 737ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 738ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark nextTSpan = testTSpanBase->upCast()->next(); 739ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark endT = nextTSpan->t(); 740ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (endT >= bestT) { 741ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 7424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 743ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark testTSpanBase = nextTSpan; 744ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while (testTSpanBase); 745ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* bestTSpan = NULL; 746ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* testTSpan = testTSpanBase->upCast(); 747ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!testTSpan->isCanceled()) { 748ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *hitT = bestT; 749ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bestTSpan = testTSpan; 750ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *hitSomething = true; 751570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 752ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return bestTSpan; 75307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 75407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 755ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::detach(const SkOpSpan* span) { 756ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->done()) { 757ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark --this->fDoneCount; 758dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 759ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark --this->fCount; 760dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 761dac1d17027dcaa5596885a9f333979418b35001ccaryclark 762ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkdouble SkOpSegment::distSq(double t, SkOpAngle* oppAngle) { 763ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDPoint testPt = this->dPtAtT(t); 764ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDLine testPerp = {{ testPt, testPt }}; 765ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDVector slope = this->dSlopeAtT(t); 766ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark testPerp[1].fX += slope.fY; 767ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark testPerp[1].fY -= slope.fX; 768ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkIntersections i; 769ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* oppSegment = oppAngle->segment(); 770ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppPtCount = SkPathOpsVerbToPoints(oppSegment->verb()); 771ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (*CurveIntersectRay[oppPtCount])(oppSegment->pts(), testPerp, &i); 772ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double closestDistSq = SK_ScalarInfinity; 773ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < i.used(); ++index) { 774ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) { 775ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 776a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 777ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double testDistSq = testPt.distanceSquared(i.pt(index)); 778ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (closestDistSq > testDistSq) { 779ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark closestDistSq = testDistSq; 780a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 781ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 782ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return closestDistSq; 7834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 7844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 78507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 78607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The M and S variable name parts stand for the operators. 78707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Mi stands for Minuend (see wiki subtraction, analogous to difference) 78807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Su stands for Subtrahend 78907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The Opp variable name part designates that the value is for the Opposite operator. 79007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Opposite values result from combining coincident spans. 79107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 792ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, 793ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) { 794ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* start = *nextStart; 795ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* end = *nextEnd; 796ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != end); 797ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 798ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 799ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (other) { 80007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 80107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 80207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 80307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 80407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 805ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* startSpan = start->starter(end); 806ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (startSpan->done()) { 807cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return NULL; 808cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 809ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(startSpan); 810ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 81107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 81207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 813ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 814ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear == end); // is this ever not end? 815ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear); 816ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != endNear); 817ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 8184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 819ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp); 820570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 8214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!sortable) { 8227eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com *unsortable = true; 823ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 8247eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com return NULL; 8257eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 826ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = this->spanToAngle(end, start); 8274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (angle->unorderable()) { 82807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 829ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 83007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 83107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 8334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 8344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 83507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 836ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumMiWinding = updateWinding(end, start); 8378cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (sumMiWinding == SK_MinS32) { 8388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = true; 839ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 8408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return NULL; 8418cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 842ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumSuWinding = updateOppWinding(end, start); 84307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 84407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 84507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 84707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 84807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 84907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // iterate through the angle, and compute everyone's winding 85007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 85107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 85207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 85307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 85407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(), 8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle->end(), op, &sumMiWinding, &sumSuWinding); 85607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 85707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 85807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 85907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 860570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com foundDone = nextSegment->done(nextAngle); 86107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 86207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 86307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 86407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 86507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 866570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 867ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 868570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 869ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = nextAngle->lastMarked(); 87007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 8714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 87207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 87307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 874ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 875ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last->segment()->debugID(), last->debugID()); 876ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!last->final()) { 877ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf(" windSum=%d", last->upCast()->windSum()); 878ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 879ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("\n"); 88007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 88107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 883ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark start->segment()->markDone(start->starter(end)); 88407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 88507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 88607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 88707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 88807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 88907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 89007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 89107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 89207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 89307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 89407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 89507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 89607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 897ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpanBase*>* chase, 898ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable) { 899ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* start = *nextStart; 900ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* end = *nextEnd; 901ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != end); 902ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 903ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 904ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (other) { 90507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 90607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 90707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 90807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 90907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 910ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* startSpan = start->starter(end); 911ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (startSpan->done()) { 912570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return NULL; 913570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 914ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(startSpan); 915ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 91607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 91707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 918ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 919ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear == end); // is this ever not end? 920ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear); 921ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != endNear); 922ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 9234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 924ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding); 925570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 92607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!sortable) { 92707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 928ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 929ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 930ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 931ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = this->spanToAngle(end, start); 932ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (angle->unorderable()) { 933ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *unsortable = true; 934ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 93507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 93607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 9374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 9384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 9394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 94007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 941ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int sumWinding = updateWinding(end, start); 9424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 94307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 94407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 945ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // iterate through the angle, and compute everyone's winding 94607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 94707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 94807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 94907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 95007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(), 9514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &sumWinding); 95207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 95307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 95407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 95507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 95607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundDone = nextSegment->done(nextAngle); 95707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 95807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 95907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 96007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 96107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 962570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 963ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 964570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 965ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = nextAngle->lastMarked(); 96607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 9674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 96807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 96907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 970ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 971ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last->segment()->debugID(), last->debugID()); 972ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!last->final()) { 973ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf(" windSum=%d", last->upCast()->windSum()); 974ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 975ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("\n"); 97607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 97707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 9784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 979ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark start->segment()->markDone(start->starter(end)); 98007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 98107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 98207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 98307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 98407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 98507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 98607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 98707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 98807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 98907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 99007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 99107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 99207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 993ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, 994ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool* unsortable) { 995ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* start = *nextStart; 996ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* end = *nextEnd; 997ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != end); 998ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 999ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 1000ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (other) { 1001ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // mark the smaller of startIndex, endIndex done, and all adjacent 1002ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // spans with the same T value (but not 'other' spans) 100307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 100407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 100507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 1006ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* startSpan = start->starter(end); 1007ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (startSpan->done()) { 100807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 100907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1010ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(startSpan); 1011ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 101207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 101307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1014ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \ 1015ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark : (*nextStart)->prev()); 1016ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear == end); // is this ever not end? 1017ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endNear); 1018ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(start != endNear); 1019ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 1020ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = this->spanToAngle(end, start); 1021ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (angle->unorderable()) { 1022ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *unsortable = true; 1023ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(start->starter(end)); 1024ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 1025ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 10264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 10274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 10284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 1029570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 10304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 103107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 103207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 1033ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // iterate through the angle, and compute everyone's winding 103407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 103507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 103607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 103707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 103807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 103907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 104007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!(foundDone = nextSegment->done(nextAngle))) { 10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 104407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 10454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle = nextAngle->next(); 10464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (nextAngle != angle); 1047ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark start->segment()->markDone(start->starter(end)); 104807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 104907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 105007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 105107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 105207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 105307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 105407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 105507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 105607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 105707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 105807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 105907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 106007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1061ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr, 1062ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool* unsortable, SkChunkAlloc* allocator) { 106307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // iterate through T intersections and return topmost 106407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // topmost tangent from y-min to first pt is closer to horizontal 106507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!done()); 1066ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* firstT = NULL; 1067ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) this->activeLeftTop(&firstT); 1068ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!firstT) { 10698cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = !firstPass; 1070ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark firstT = &fHead; 1071ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while (firstT->upCast()->done()) { 1072ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark firstT = firstT->upCast()->next(); 107307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1074ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *startPtr = firstT; 1075ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *endPtr = firstT->upCast()->next(); 107607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return this; 107707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 107807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // sort the edges to find the leftmost 107907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = 1; 1080ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* end; 1081ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (firstT->final() || firstT->upCast()->done()) { 108207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com step = -1; 1083ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark end = firstT->prev(); 1084ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(end); 1085ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else { 1086ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark end = firstT->upCast()->next(); 108707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 108807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if the topmost T is not on end, or is three-way or more, find left 108907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // look for left-ness from tLeft to firstT (matching y of other) 1090ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(firstT != end); 10914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* markAngle = spanToAngle(firstT, end); 10924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!markAngle) { 1093ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markAngle = addSingletonAngles(step, allocator); 10944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org markAngle->markStops(); 1096e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle 1097e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark : markAngle->findFirst(); 10984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!baseAngle) { 10994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; // nothing to do 1100570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 110107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar top = SK_ScalarMax; 11024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpAngle* firstAngle = NULL; 11034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpAngle* angle = baseAngle; 11044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 11054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!angle->unorderable()) { 1106ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSegment* next = angle->segment(); 11074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPathOpsBounds bounds; 11084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org next->subDivideBounds(angle->end(), angle->start(), &bounds); 110965f553182ab7069378ef863d30094d0327f178d0caryclark bool nearSame = AlmostEqualUlps(top, bounds.top()); 111065f553182ab7069378ef863d30094d0327f178d0caryclark bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->sectorStart(); 111165f553182ab7069378ef863d30094d0327f178d0caryclark bool lesserSector = top > bounds.fTop; 111265f553182ab7069378ef863d30094d0327f178d0caryclark if (lesserSector && (!nearSame || lowerSector)) { 11134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org top = bounds.fTop; 11144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle = angle; 11154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 111607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 11174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = angle->next(); 11184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (angle != baseAngle); 111965f553182ab7069378ef863d30094d0327f178d0caryclark if (!firstAngle) { 112065f553182ab7069378ef863d30094d0327f178d0caryclark return NULL; // if all are unorderable, give up 112165f553182ab7069378ef863d30094d0327f178d0caryclark } 11224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 11234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 11244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle->debugLoop(); 112507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 112607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // skip edges that have already been processed 11274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = firstAngle; 11288cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkOpSegment* leftSegment = NULL; 11298cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org bool looped = false; 113007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 11318cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = angle->unorderable(); 11328cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (firstPass || !*unsortable) { 11338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org leftSegment = angle->segment(); 1134ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *startPtr = angle->end(); 1135ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *endPtr = angle->start(); 1136ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpan* firstSpan = (*startPtr)->starter(*endPtr); 1137ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!firstSpan->done()) { 11388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org break; 11398cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 11408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 11414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = angle->next(); 11428cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org looped = true; 11438cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } while (angle != firstAngle); 11448cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (angle == firstAngle && looped) { 11458cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return NULL; 11468cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 114707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (leftSegment->verb() >= SkPath::kQuad_Verb) { 1148ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* start = *startPtr; 1149ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* end = *endPtr; 1150e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark bool swap; 1151ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!leftSegment->clockwise(start, end, &swap)) { 115207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #if DEBUG_SWAP_TOP 1153ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s swap=%d inflections=%d monotonic=%d\n", 11548cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org __FUNCTION__, 1155ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark swap, leftSegment->debugInflections(start, end), 1156ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark leftSegment->monotonicInY(start, end)); 115707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 115807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (swap) { 115907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not the first 116007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // sorted but merely the first not already processed (i.e., not done) 1161ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap(*startPtr, *endPtr); 116207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 116307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 116407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 116507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return leftSegment; 116607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 116707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1168ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpGlobalState* SkOpSegment::globalState() const { 1169ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return contour()->globalState(); 117065f553182ab7069378ef863d30094d0327f178d0caryclark} 117165f553182ab7069378ef863d30094d0327f178d0caryclark 1172ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::init(SkPoint pts[], SkOpContour* contour, SkPath::Verb verb) { 1173ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fContour = contour; 1174ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fNext = NULL; 117507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fPts = pts; 117607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fVerb = verb; 1177ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fCount = 0; 1178ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fDoneCount = 0; 1179ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fVisited = false; 1180ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* zeroSpan = &fHead; 1181ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark zeroSpan->init(this, NULL, 0, fPts[0]); 1182ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* oneSpan = &fTail; 1183ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark zeroSpan->setNext(oneSpan); 1184ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]); 1185ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark PATH_OPS_DEBUG_CODE(fID = globalState()->nextSegmentID()); 1186ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1187ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 1188ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::initWinding(SkOpSpanBase* start, SkOpSpanBase* end, 1189ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle::IncludeType angleIncludeType) { 1190ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int local = SkOpSegment::SpanSign(start, end); 119165f553182ab7069378ef863d30094d0327f178d0caryclark SkDEBUGCODE(bool success); 11924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (angleIncludeType == SkOpAngle::kBinarySingle) { 1193ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppLocal = SkOpSegment::OppSign(start, end); 119465f553182ab7069378ef863d30094d0327f178d0caryclark SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, oppLocal, NULL); 119507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZATION: the reverse mark and chase could skip the first marking 119665f553182ab7069378ef863d30094d0327f178d0caryclark SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, oppLocal, NULL); 11974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 119865f553182ab7069378ef863d30094d0327f178d0caryclark SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, NULL); 11994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // OPTIMIZATION: the reverse mark and chase could skip the first marking 120065f553182ab7069378ef863d30094d0327f178d0caryclark SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, NULL); 12014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 120265f553182ab7069378ef863d30094d0327f178d0caryclark SkASSERT(success); 120307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 120407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 120507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 120607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comwhen we start with a vertical intersect, we try to use the dx to determine if the edge is to 120707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe left or the right of vertical. This determines if we need to add the span's 120807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comsign or not. However, this isn't enough. 120907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf the supplied sign (winding) is zero, then we didn't hit another vertical span, so dx is needed. 121007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf there was a winding, then it may or may not need adjusting. If the span the winding was borrowed 121107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comfrom has the same x direction as this span, the winding should change. If the dx is opposite, then 121207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe same winding is shared by both. 121307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com*/ 1214ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::initWinding(SkOpSpanBase* start, SkOpSpanBase* end, double tHit, 1215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int winding, SkScalar hitDx, int oppWind, SkScalar hitOppDx) { 1216ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(this == start->segment()); 121707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(hitDx || !winding); 1218277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 1219ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// SkASSERT(dx); 1220ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int windVal = start->starter(end)->windValue(); 122107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 1222dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, debugID(), winding, 122307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); 122407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 12254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int sideWind = winding + (dx < 0 ? windVal : -windVal); 12264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (abs(winding) < abs(sideWind)) { 12274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org winding = sideWind; 122807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1229ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDEBUGCODE(int oppLocal = SkOpSegment::OppSign(start, end)); 123007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(hitOppDx || !oppWind || !oppLocal); 1231ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppWindVal = start->starter(end)->oppValue(); 123207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!oppWind) { 123307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWind = dx < 0 ? oppWindVal : -oppWindVal; 123407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else if (hitOppDx * dx >= 0) { 123507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 123607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (abs(oppWind) < abs(oppSideWind)) { 123707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWind = oppSideWind; 123807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 123907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1240dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING_AT_T 1241dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind); 1242dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 124365f553182ab7069378ef863d30094d0327f178d0caryclark // if this fails to mark (because the edges are too small) inform caller to try again 124465f553182ab7069378ef863d30094d0327f178d0caryclark bool success = markAndChaseWinding(start, end, winding, oppWind, NULL); 12457eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com // OPTIMIZATION: the reverse mark and chase could skip the first marking 124665f553182ab7069378ef863d30094d0327f178d0caryclark success |= markAndChaseWinding(end, start, winding, oppWind, NULL); 124765f553182ab7069378ef863d30094d0327f178d0caryclark return success; 124807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 124907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1250ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::isClose(double t, const SkOpSegment* opp) const { 1251ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDPoint cPt = this->dPtAtT(t); 1252ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int pts = SkPathOpsVerbToPoints(this->verb()); 1253ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDVector dxdy = (*CurveDSlopeAtT[pts])(this->pts(), t); 1254ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; 1255ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkIntersections i; 1256ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppPts = SkPathOpsVerbToPoints(opp->verb()); 1257ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (*CurveIntersectRay[oppPts])(opp->pts(), perp, &i); 1258ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int used = i.used(); 1259ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < used; ++index) { 1260ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (cPt.roughlyEqual(i.pt(index))) { 1261866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org return true; 1262866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org } 1263ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1264a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 1265a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 1266a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 1267ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::isXor() const { 1268ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return fContour->isXor(); 126907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 127007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1271ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end) { 1272ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 1273ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* minSpan = start->starter(end); 1274ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark markDone(minSpan); 1275ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = NULL; 127607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 1277ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((other = other->nextChase(&start, &step, &minSpan, &last))) { 127807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->done()) { 1279dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 1280dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 128107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1282ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark other->markDone(minSpan); 128307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 128407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 128507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 128607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1287ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding, 1288ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** lastPtr) { 1289ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* spanStart = start->starter(end); 1290ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 1291ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool success = markWinding(spanStart, winding); 1292ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = NULL; 12934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = this; 1294ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 1295ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (spanStart->windSum() != SK_MinS32) { 1296ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(spanStart->windSum() == winding); 1297dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 1298dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 12994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1300ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) other->markWinding(spanStart, winding); 13016f726addf3178b01949bb389ef83cf14a1d7b6b2caryclark } 130265f553182ab7069378ef863d30094d0327f178d0caryclark if (lastPtr) { 130365f553182ab7069378ef863d30094d0327f178d0caryclark *lastPtr = last; 130465f553182ab7069378ef863d30094d0327f178d0caryclark } 130565f553182ab7069378ef863d30094d0327f178d0caryclark return success; 13064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 13074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1308ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, 1309ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int winding, int oppWinding, SkOpSpanBase** lastPtr) { 1310ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* spanStart = start->starter(end); 1311ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int step = start->step(end); 1312ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool success = markWinding(spanStart, winding, oppWinding); 1313ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = NULL; 131407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 1315ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 1316ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (spanStart->windSum() != SK_MinS32) { 1317ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->operand() == other->operand()) { 1318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(spanStart->windSum() == winding); 1319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (spanStart->oppSum() != oppWinding) { 1320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark this->globalState()->setWindingFailed(); 1321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return false; 1322dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else { 1324ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(spanStart->windSum() == oppWinding); 1325ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(spanStart->oppSum() == winding); 1326dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1327dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 1328dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1329dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1330ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->operand() == other->operand()) { 1331ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) other->markWinding(spanStart, winding, oppWinding); 1332dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) other->markWinding(spanStart, oppWinding, winding); 133407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 133507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 133665f553182ab7069378ef863d30094d0327f178d0caryclark if (lastPtr) { 133765f553182ab7069378ef863d30094d0327f178d0caryclark *lastPtr = last; 133865f553182ab7069378ef863d30094d0327f178d0caryclark } 133965f553182ab7069378ef863d30094d0327f178d0caryclark return success; 134007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 134107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1342ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { 134307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 134407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 134507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 134607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1347ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last; 1348ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, &last); 1349570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 1350570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 1351ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s last seg=%d span=%d", __FUNCTION__, 1352ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last->segment()->debugID(), last->debugID()); 1353ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!last->final()) { 1354ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf(" windSum="); 1355ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 1356ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1357ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("\n"); 1358570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1359570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 136007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 136107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 136207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1363ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding, 1364ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppSumWinding, const SkOpAngle* angle) { 136507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 136607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 136707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 136807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 136907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { 137007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppMaxWinding = oppSumWinding; 137107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1372ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* last = NULL; 137365f553182ab7069378ef863d30094d0327f178d0caryclark // caller doesn't require that this marks anything 1374ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, &last); 1375570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 1376570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 1377ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s last segment=%d span=%d", __FUNCTION__, 1378ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark last->segment()->debugID(), last->debugID()); 1379ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!last->final()) { 1380ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf(" windSum="); 1381ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 1382ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1383ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf(" \n"); 1384570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1385570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 138607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 138707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 138807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1389ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::markDone(SkOpSpan* span) { 1390ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(this == span->segment()); 1391ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->done()) { 139207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 139307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1394ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#if DEBUG_MARK_DONE 1395ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum()); 1396ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1397ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setDone(true); 1398ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark ++fDoneCount; 1399ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 140007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 140107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1402ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding) { 1403ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(this == span->segment()); 1404ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(winding); 1405ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->done()) { 140665f553182ab7069378ef863d30094d0327f178d0caryclark return false; 140707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 140807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 1409ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugShowNewWinding(__FUNCTION__, span, winding); 14108cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 1411ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setWindSum(winding); 1412ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 141365f553182ab7069378ef863d30094d0327f178d0caryclark return true; 141407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 141507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1416ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding, int oppWinding) { 1417ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(this == span->segment()); 1418ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(winding || oppWinding); 1419ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->done()) { 142065f553182ab7069378ef863d30094d0327f178d0caryclark return false; 142107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 142207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 1423ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugShowNewWinding(__FUNCTION__, span, winding, oppWinding); 14248cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 1425ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setWindSum(winding); 1426ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setOppSum(oppWinding); 14274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 142865f553182ab7069378ef863d30094d0327f178d0caryclark return true; 142907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 143007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1431ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::match(const SkOpPtT* base, const SkOpSegment* testParent, double testT, 1432ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkPoint& testPt) const { 1433ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSegment* baseParent = base->segment(); 1434ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this == baseParent && this == testParent && precisely_equal(base->fT, testT)) { 1435ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return true; 143607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1437ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) { 1438ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return false; 1439e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 1440ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return !ptsDisjoint(base->fT, base->fPt, testT, testPt); 1441ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1442ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 1443ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) { 1444ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (last) { 1445ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *last = endSpan; 144607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1447ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return NULL; 144807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 144907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1450ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* end) const { 14518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(fVerb != SkPath::kLine_Verb); 145207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 1453ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDQuad dst = SkDQuad::SubDivide(fPts, start->t(), end->t()); 145407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return dst.monotonicInY(); 145507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 145607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1457ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t()); 145807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return dst.monotonicInY(); 145907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 146007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1461ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, 1462ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** end) { 1463ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while (span->final() || span->upCast()->done()) { 1464ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->final()) { 146507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return false; 146607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1467ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span = span->upCast()->next(); 146807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1469ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *start = span; 1470ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *end = span->upCast()->next(); 147107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return true; 147207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 147307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1474ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkSkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr, 1475ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase** last) const { 1476ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* origStart = *startPtr; 1477dac1d17027dcaa5596885a9f333979418b35001ccaryclark int step = *stepPtr; 1478ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev(); 1479ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(endSpan); 1480ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle(); 1481ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* foundSpan; 1482ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* otherEnd; 1483dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other; 1484dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (angle == NULL) { 1485ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (endSpan->t() != 0 && endSpan->t() != 1) { 1486dac1d17027dcaa5596885a9f333979418b35001ccaryclark return NULL; 1487dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1488ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* otherPtT = endSpan->ptT()->next(); 1489ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark other = otherPtT->segment(); 1490ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark foundSpan = otherPtT->span(); 1491ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark otherEnd = step > 0 ? foundSpan->upCast()->next() : foundSpan->prev(); 1492dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1493dac1d17027dcaa5596885a9f333979418b35001ccaryclark int loopCount = angle->loopCount(); 1494dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (loopCount > 2) { 1495ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return set_last(last, endSpan); 1496dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1497dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpAngle* next = angle->next(); 149865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (NULL == next) { 149965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 150065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 1501dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING 1502ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (angle->sign() != next->sign() && !angle->segment()->contour()->isXor() 1503ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark && !next->segment()->contour()->isXor()) { 1504dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s mismatched signs\n", __FUNCTION__); 1505dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1506ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#endif 1507dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = next->segment(); 1508ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark foundSpan = endSpan = next->start(); 1509dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherEnd = next->end(); 1510570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1511ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int foundStep = foundSpan->step(otherEnd); 1512dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (*stepPtr != foundStep) { 1513ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return set_last(last, endSpan); 151407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1515ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(*startPtr); 1516ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!otherEnd) { 151765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 151865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 151965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// SkASSERT(otherEnd >= 0); 1520ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast(); 1521ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* foundMin = foundSpan->starter(otherEnd); 1522ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (foundMin->windValue() != origMin->windValue() 1523ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark || foundMin->oppValue() != origMin->oppValue()) { 1524ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return set_last(last, endSpan); 1525dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1526ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *startPtr = foundSpan; 1527dac1d17027dcaa5596885a9f333979418b35001ccaryclark *stepPtr = foundStep; 1528dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (minPtr) { 1529dac1d17027dcaa5596885a9f333979418b35001ccaryclark *minPtr = foundMin; 1530a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 153107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 153207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 153307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1534ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic void clear_visited(SkOpSpan* span) { 1535ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // reset visited flag back to false 1536ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1537ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 1538ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((ptT = ptT->next()) != stopPtT) { 1539ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* opp = ptT->segment(); 1540ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark opp->resetVisited(); 154107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1542ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((span = span->next()->upCastable())); 154307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 154407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1545ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// look for pairs of undetected coincident curves 1546ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// assumes that segments going in have visited flag clear 1547ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// curve/curve intersection should now do a pretty good job of finding coincident runs so 1548ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// this may be only be necessary for line/curve pairs -- so skip unless this is a line and the 1549ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// the opp is not a line 1550ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) { 1551ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->verb() != SkPath::kLine_Verb) { 1552ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return; 1553ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1554ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* prior = NULL; 1555ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* span = &fHead; 1556ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1557ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* ptT = span->ptT(), * spanStopPtT = ptT; 1558ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(ptT->span() == span); 1559ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((ptT = ptT->next()) != spanStopPtT) { 1560ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* opp = ptT->span()->segment(); 1561ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (opp->setVisited()) { 1562570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 1563570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1564ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (opp->verb() == SkPath::kLine_Verb) { 1565ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1566ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1567ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->containsCoincidence(opp)) { // FIXME: this assumes that if the opposite 1568ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // segment is coincident then no more coincidence 1569ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // needs to be detected. This may not be true. 1570ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1571ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1572ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span->containsCoinEnd(opp)) { 1573ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1574ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1575ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // if already visited and visited again, check for coin 1576ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (span == &fHead) { 1577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1578ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1579ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* priorPtT = NULL, * priorStopPtT; 1580ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // find prior span containing opp segment 1581ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* priorOpp = NULL; 1582ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark prior = span; 1583ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while (!priorOpp && (prior = prior->prev())) { 1584ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark priorStopPtT = priorPtT = prior->ptT(); 1585ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 1586ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSegment* segment = priorPtT->span()->segment(); 1587ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (segment == opp) { 1588ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark priorOpp = opp; 1589ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark break; 1590ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1591ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1592ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1593ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!priorOpp) { 1594ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1595ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1596ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* oppStart = prior->ptT(); 1597ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* oppEnd = span->ptT(); 1598ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool swapped = priorPtT->fT > ptT->fT; 1599ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (swapped) { 1600ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap(priorPtT, ptT); 1601ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap(oppStart, oppEnd); 1602ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1603ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool flipped = oppStart->fT > oppEnd->fT; 1604ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark bool coincident; 1605ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) { 1606ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark goto swapBack; 1607ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1608ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark { 1609ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // average t, find mid pt 1610ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double midT = (prior->t() + span->t()) / 2; 1611ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint midPt = this->ptAtT(midT); 1612ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark coincident = true; 1613ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // if the mid pt is not near either end pt, project perpendicular through opp seg 1614ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt) 1615ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) { 1616ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark coincident = false; 1617ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkIntersections i; 1618ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int ptCount = SkPathOpsVerbToPoints(this->verb()); 1619ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkVector dxdy = (*CurveSlopeAtT[ptCount])(pts(), midT); 1620ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDLine ray = {{{midPt.fX, midPt.fY}, 1621ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark {midPt.fX + dxdy.fY, midPt.fY - dxdy.fX}}}; 1622ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppPtCount = SkPathOpsVerbToPoints(opp->verb()); 1623ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (*CurveIntersectRay[oppPtCount])(opp->pts(), ray, &i); 1624ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // measure distance and see if it's small enough to denote coincidence 1625ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark for (int index = 0; index < i.used(); ++index) { 1626ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDPoint oppPt = i.pt(index); 1627ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oppPt.approximatelyEqual(midPt)) { 1628ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkVector oppDxdy = (*CurveSlopeAtT[oppPtCount])(opp->pts(), 1629ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark i[index][0]); 1630ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oppDxdy.normalize(); 1631ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark dxdy.normalize(); 1632ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy) / FLT_EPSILON); 1633ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark coincident |= flatness < 5000; // FIXME: replace with tuned value 1634ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1635ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1636ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1637ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1638ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (coincident) { 1639ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // mark coincidence 1640ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator); 1641ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark clear_visited(&fHead); 1642ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark missingCoincidence(coincidences, allocator); 1643ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return; 1644ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1645ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark swapBack: 1646ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (swapped) { 1647ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkTSwap(priorPtT, ptT); 1648ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1649570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1650ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((span = span->next()->upCastable())); 1651ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark clear_visited(&fHead); 1652ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1653ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 1654ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 1655ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::moveNearby() { 1656ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 1657ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* spanS = &fHead; 1658ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1659ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* test = spanS->upCast()->next(); 1660ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* next; 1661ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (spanS->contains(test)) { 1662ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!test->final()) { 1663ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark test->upCast()->detach(spanS->ptT()); 1664ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1665ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else if (spanS != &fHead) { 1666ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanS->upCast()->detach(test->ptT()); 1667ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanS = test; 1668570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 1669570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 167007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1671ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { // iterate through all spans associated with start 1672ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* startBase = spanS->ptT(); 1673ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark next = test->final() ? NULL : test->upCast()->next(); 1674ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1675ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* testBase = test->ptT(); 1676ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1677ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (startBase == testBase) { 1678ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark goto checkNextSpan; 1679ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1680ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (testBase->duplicate()) { 1681ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1682ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1683ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) { 1684ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (test == &this->fTail) { 1685ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (spanS == &fHead) { 1686ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 1687ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return true; // if this span has collapsed, remove it from parent 1688ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1689ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark this->fTail.merge(spanS->upCast()); 1690ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 1691ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return true; 1692ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1693ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanS->merge(test->upCast()); 1694ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanS->upCast()->setNext(next); 1695ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark goto checkNextSpan; 1696ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1697ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((testBase = testBase->next()) != test->ptT()); 1698ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((startBase = startBase->next()) != spanS->ptT()); 1699ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark checkNextSpan: 1700ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark ; 1701ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((test = next)); 1702ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark spanS = spanS->upCast()->next(); 1703ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while (!spanS->final()); 1704ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugValidate(); 1705ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return true; 170607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 170707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1708ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::operand() const { 1709ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return fContour->operand(); 1710dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1711dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1712ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::oppXor() const { 1713ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return fContour->oppXor(); 17145e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark} 17155e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark 1716ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const { 1717ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (fVerb == SkPath::kLine_Verb) { 1718ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return false; 1719dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1720ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // quads (and cubics) can loop back to nearly a line so that an opposite curve 1721ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // hits in two places with very different t values. 1722ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // OPTIMIZATION: curves could be preflighted so that, for example, something like 1723ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // 'controls contained by ends' could avoid this check for common curves 1724ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // 'ends are extremes in x or y' is cheaper to compute and real-world common 1725ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark // on the other hand, the below check is relatively inexpensive 1726ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double midT = (t1 + t2) / 2; 1727ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint midPt = this->ptAtT(midT); 1728ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double seDistSq = SkTMax(pt1.distanceToSqd(pt2) * 2, FLT_EPSILON * 2); 1729ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return midPt.distanceToSqd(pt1) > seDistSq || midPt.distanceToSqd(pt2) > seDistSq; 1730ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1731ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 1732ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 1733ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int* maxWinding, int* sumWinding) { 1734ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int deltaSum = SpanSign(start, end); 1735ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *maxWinding = *sumMiWinding; 1736ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *sumWinding = *sumMiWinding -= deltaSum; 1737ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 1738dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1739dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1740ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 1741ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding, 1742ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int* oppSumWinding) { 1743ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int deltaSum = SpanSign(start, end); 1744ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppDeltaSum = OppSign(start, end); 174507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 174607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumSuWinding; 174707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumSuWinding -= deltaSum; 174807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumMiWinding; 174907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumMiWinding -= oppDeltaSum; 175007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 175107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumMiWinding; 175207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumMiWinding -= deltaSum; 175307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumSuWinding; 175407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumSuWinding -= oppDeltaSum; 175507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1756ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 1757ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM); 175807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 175907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 17604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::sortAngles() { 1761ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* span = &this->fHead; 17624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 1763ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* fromAngle = span->fromAngle(); 1764ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* toAngle = span->final() ? NULL : span->upCast()->toAngle(); 1765dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!fromAngle && !toAngle) { 17664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 17674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1768cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#if DEBUG_ANGLE 17694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool wroteAfterHeader = false; 1770cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#endif 1771ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* baseAngle = fromAngle; 1772ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (fromAngle && toAngle) { 17734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 1774ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(), 1775ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->debugID()); 1776ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark wroteAfterHeader = true; 17774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 1778ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark fromAngle->insert(toAngle); 1779ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } else if (!fromAngle) { 1780ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark baseAngle = toAngle; 178107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1782ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 17834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 1784ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpanBase* oSpan = ptT->span(); 1785ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oSpan == span) { 1786ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark continue; 1787ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 1788ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpAngle* oAngle = oSpan->fromAngle(); 1789dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oAngle) { 1790570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_ANGLE 17914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!wroteAfterHeader) { 1792ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 1793ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->t(), span->debugID()); 17944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org wroteAfterHeader = true; 17954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1796570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 1797ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!oAngle->loopContains(baseAngle)) { 17988cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org baseAngle->insert(oAngle); 17998cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 18004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1801ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!oSpan->final()) { 1802ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark oAngle = oSpan->upCast()->toAngle(); 1803ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (oAngle) { 18044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 1805ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!wroteAfterHeader) { 1806ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 1807ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->t(), span->debugID()); 1808ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark wroteAfterHeader = true; 1809ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 18104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 1811ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!oAngle->loopContains(baseAngle)) { 1812ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark baseAngle->insert(oAngle); 1813ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 18148cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 18154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1816ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((ptT = ptT->next()) != stopPtT); 1817ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (baseAngle->loopCount() == 1) { 1818ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->setFromAngle(NULL); 1819ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (toAngle) { 1820ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark span->upCast()->setToAngle(NULL); 18214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 18224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = NULL; 18234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 18244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 18254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!baseAngle || baseAngle->loopCount() > 1); 18264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 1827ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while (!span->final() && (span = span->upCast()->next())); 1828570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1829570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1830cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed 1831ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, 1832ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPoint edge[4]) const { 1833cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 1834ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpPtT& startPtT = *start->ptT(); 1835ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpPtT& endPtT = *end->ptT(); 1836ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark edge[0] = startPtT.fPt; 1837cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 1838ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark edge[points] = endPtT.fPt; 1839cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 1840cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1841cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1842ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double startT = startPtT.fT; 1843ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double endT = endPtT.fT; 1844cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 1845cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 184607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 1847cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[1]; 1848cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 184907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1850cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1851cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (start < end) { 1852cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[1]; 1853cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = fPts[2]; 1854cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1855cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1856cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[2]; 1857cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = fPts[1]; 1858cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1859cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1860cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com const SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[points].fX, edge[points].fY }}; 1861cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 1862cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoint(); 1863cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 1864cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1865cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDPoint ctrl[2]; 1866cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl); 1867cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = ctrl[0].asSkPoint(); 1868cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = ctrl[1].asSkPoint(); 186907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1870cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 1871cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com} 1872cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 1873ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, 1874ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkDCubic* result) const { 1875cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 1876ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpPtT& startPtT = *start->ptT(); 1877ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpPtT& endPtT = *end->ptT(); 1878ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (*result)[0].set(startPtT.fPt); 1879cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 1880ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark (*result)[points].set(endPtT.fPt); 1881cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 1882cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1883cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1884ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double startT = startPtT.fT; 1885ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark double endT = endPtT.fT; 1886cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 1887cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 1888cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 1889cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[1]); 1890cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1891cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1892cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1893ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (startT == 0) { 1894cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[1]); 1895cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[2].set(fPts[2]); 1896cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1897cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1898cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[2]); 1899cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[2].set(fPts[1]); 1900cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1901cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1902cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 1903cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1] = SkDQuad::SubDivide(fPts, (*result)[0], (*result)[2], startT, endT); 1904cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 1905cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1906cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDCubic::SubDivide(fPts, (*result)[0], (*result)[3], startT, endT, &(*result)[1]); 1907cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1908cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 190907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 191007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1911ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end, 1912ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkPathOpsBounds* bounds) const { 191307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint edge[4]; 191407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com subDivide(start, end, edge); 1915277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge); 191607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 191707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1918ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkvoid SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { 1919ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkOpSpan* span = this->head(); 1920ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark do { 1921ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (!span->done()) { 192207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 192307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1924ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } while ((span = span->next()->upCastable())); 1925ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkASSERT(span); 1926ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *start = span; 1927ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark *end = span->next(); 192807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 192907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1930ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { 1931ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpan* lesser = start->starter(end); 1932ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppWinding = lesser->oppSum(); 1933ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int oppSpanWinding = SkOpSegment::OppSign(start, end); 193407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding) 193507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com && oppWinding != SK_MaxS32) { 193607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWinding -= oppSpanWinding; 193707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 193807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return oppWinding; 193907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 194007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 194107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(const SkOpAngle* angle) const { 1942ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* startSpan = angle->start(); 1943ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* endSpan = angle->end(); 1944ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return updateOppWinding(endSpan, startSpan); 194507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 194607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 194707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { 1948ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* startSpan = angle->start(); 1949ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* endSpan = angle->end(); 1950ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return updateOppWinding(startSpan, endSpan); 195107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 195207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1953ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::updateWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { 1954ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpan* lesser = start->starter(end); 1955ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int winding = lesser->windSum(); 19568cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (winding == SK_MinS32) { 19578cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return winding; 19588cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 1959ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int spanWinding = SkOpSegment::SpanSign(start, end); 1960570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (winding && UseInnerWinding(winding - spanWinding, winding) 1961570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && winding != SK_MaxS32) { 196207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com winding -= spanWinding; 196307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 196407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return winding; 196507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 196607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 196707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWinding(const SkOpAngle* angle) const { 1968ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* startSpan = angle->start(); 1969ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* endSpan = angle->end(); 1970ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return updateWinding(endSpan, startSpan); 1971570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1972570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 197307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWindingReverse(const SkOpAngle* angle) const { 1974ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* startSpan = angle->start(); 1975ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpanBase* endSpan = angle->end(); 1976ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return updateWinding(startSpan, endSpan); 1977570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1978570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1979570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// OPTIMIZATION: does the following also work, and is it any faster? 1980570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// return outerWinding * innerWinding > 0 1981570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0))) 1982570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) { 1983570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(outerWinding != SK_MaxS32); 1984570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(innerWinding != SK_MaxS32); 1985570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absOut = abs(outerWinding); 1986570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absIn = abs(innerWinding); 1987570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; 1988570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return result; 1989570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1990570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1991ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkint SkOpSegment::windingAtT(double tHit, const SkOpSpan* span, bool crossOpp, 1992ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark SkScalar* dx) const { 1993ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark if (approximately_zero(tHit - span->t())) { // if we hit the end of a span, disregard 199407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; 199507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1996ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int winding = crossOpp ? span->oppSum() : span->windSum(); 199707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(winding != SK_MinS32); 1998ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark int windVal = crossOpp ? span->oppValue() : span->windValue(); 199907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 2000dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __FUNCTION__, 2001ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark debugID(), crossOpp, tHit, span->t(), winding, windVal); 200207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 200307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // see if a + change in T results in a +/- change in X (compute x'(T)) 2004277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 200507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { 200607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *dx = fPts[2].fX - fPts[1].fX - *dx; 200707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 200807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (*dx == 0) { 200907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 201007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf(" dx=0 winding=SK_MinS32\n"); 201107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 201207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; 201307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2014a4aced47281e085201a356ce888b92138846e9f6skia.committer@gmail.com if (windVal < 0) { // reverse sign if opp contour traveled in reverse 201507e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com *dx = -*dx; 201607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 201707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (winding * *dx > 0) { // if same signs, result is negative 201807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com winding += *dx > 0 ? -windVal : windVal; 201907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 202007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 202107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); 202207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 202307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return winding; 202407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 202507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 202607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windSum(const SkOpAngle* angle) const { 2027ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark const SkOpSpan* minSpan = angle->start()->starter(angle->end()); 2028ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark return minSpan->windSum(); 202907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 2030