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 */ 754359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpCoincidence.h" 8dac1d17027dcaa5596885a9f333979418b35001ccaryclark#include "SkOpContour.h" 907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h" 1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h" 1154359294a7c9dc54802d512a5d891a35c1663392caryclark 1254359294a7c9dc54802d512a5d891a35c1663392caryclark/* 1354359294a7c9dc54802d512a5d891a35c1663392caryclarkAfter computing raw intersections, post process all segments to: 1454359294a7c9dc54802d512a5d891a35c1663392caryclark- find small collections of points that can be collapsed to a single point 1554359294a7c9dc54802d512a5d891a35c1663392caryclark- find missing intersections to resolve differences caused by different algorithms 1654359294a7c9dc54802d512a5d891a35c1663392caryclark 1754359294a7c9dc54802d512a5d891a35c1663392caryclarkConsider segments containing tiny or small intervals. Consider coincident segments 1854359294a7c9dc54802d512a5d891a35c1663392caryclarkbecause coincidence finds intersections through distance measurement that non-coincident 1954359294a7c9dc54802d512a5d891a35c1663392caryclarkintersection tests cannot. 2054359294a7c9dc54802d512a5d891a35c1663392caryclark */ 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 3154359294a7c9dc54802d512a5d891a35c1663392caryclarkstatic const bool gActiveEdge[kXOR_SkPathOp + 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 4554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr, 46bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpanBase** endPtr, bool* done) { 47bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) { 484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return result; 4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 50bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) { 5154359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 5396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 5654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr, 57bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpanBase** endPtr, bool* done) { 5854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* upSpan = start->upCastable(); 5954359294a7c9dc54802d512a5d891a35c1663392caryclark if (upSpan) { 6054359294a7c9dc54802d512a5d891a35c1663392caryclark if (upSpan->windValue() || upSpan->oppValue()) { 6154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* next = upSpan->next(); 6254359294a7c9dc54802d512a5d891a35c1663392caryclark if (!*endPtr) { 6354359294a7c9dc54802d512a5d891a35c1663392caryclark *startPtr = start; 6454359294a7c9dc54802d512a5d891a35c1663392caryclark *endPtr = next; 6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 6654359294a7c9dc54802d512a5d891a35c1663392caryclark if (!upSpan->done()) { 6754359294a7c9dc54802d512a5d891a35c1663392caryclark if (upSpan->windSum() != SK_MinS32) { 6854359294a7c9dc54802d512a5d891a35c1663392caryclark return spanToAngle(start, next); 694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 7354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(upSpan->done()); 7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 7654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* downSpan = start->prev(); 7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // edge leading into junction 7854359294a7c9dc54802d512a5d891a35c1663392caryclark if (downSpan) { 7954359294a7c9dc54802d512a5d891a35c1663392caryclark if (downSpan->windValue() || downSpan->oppValue()) { 8054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!*endPtr) { 8154359294a7c9dc54802d512a5d891a35c1663392caryclark *startPtr = start; 8254359294a7c9dc54802d512a5d891a35c1663392caryclark *endPtr = downSpan; 8354359294a7c9dc54802d512a5d891a35c1663392caryclark } 8454359294a7c9dc54802d512a5d891a35c1663392caryclark if (!downSpan->done()) { 8554359294a7c9dc54802d512a5d891a35c1663392caryclark if (downSpan->windSum() != SK_MinS32) { 8654359294a7c9dc54802d512a5d891a35c1663392caryclark return spanToAngle(start, downSpan); 874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 9154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(downSpan->done()); 9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 9496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 9754359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr, 98bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpanBase** endPtr, bool* done) { 9954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* oPtT = start->ptT()->next(); 10054359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* other = oPtT->segment(); 10154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* oSpan = oPtT->span(); 102bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark return other->activeAngleInner(oSpan, startPtr, endPtr, done); 10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 10554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask, 10654359294a7c9dc54802d512a5d891a35c1663392caryclark SkPathOp op) { 10754359294a7c9dc54802d512a5d891a35c1663392caryclark int sumMiWinding = this->updateWinding(end, start); 10854359294a7c9dc54802d512a5d891a35c1663392caryclark int sumSuWinding = this->updateOppWinding(end, start); 10965f553182ab7069378ef863d30094d0327f178d0caryclark#if DEBUG_LIMIT_WIND_SUM 11065f553182ab7069378ef863d30094d0327f178d0caryclark SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); 11165f553182ab7069378ef863d30094d0327f178d0caryclark SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); 11265f553182ab7069378ef863d30094d0327f178d0caryclark#endif 11354359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->operand()) { 11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 11654359294a7c9dc54802d512a5d891a35c1663392caryclark return this->activeOp(xorMiMask, xorSuMask, start, end, op, &sumMiWinding, &sumSuWinding); 11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 11954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, 12054359294a7c9dc54802d512a5d891a35c1663392caryclark SkPathOp op, int* sumMiWinding, int* sumSuWinding) { 1214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 12254359294a7c9dc54802d512a5d891a35c1663392caryclark this->setUpWindings(start, end, sumMiWinding, sumSuWinding, 1234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miFrom; 12507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miTo; 12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suFrom; 12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suTo; 12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 1294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (oppMaxWinding & xorMiMask) != 0; 1304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (oppSumWinding & xorMiMask) != 0; 1314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (maxWinding & xorSuMask) != 0; 1324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (sumWinding & xorSuMask) != 0; 13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 1344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (maxWinding & xorMiMask) != 0; 1354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (sumWinding & xorMiMask) != 0; 1364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (oppMaxWinding & xorSuMask) != 0; 1374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (oppSumWinding & xorSuMask) != 0; 13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ACTIVE_OP 141dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", 14254359294a7c9dc54802d512a5d891a35c1663392caryclark __FUNCTION__, debugID(), start->t(), end->t(), 143570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 14854359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end) { 14954359294a7c9dc54802d512a5d891a35c1663392caryclark int sumWinding = updateWinding(end, start); 15054359294a7c9dc54802d512a5d891a35c1663392caryclark return activeWinding(start, end, &sumWinding); 15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 15354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding) { 1544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding; 15554359294a7c9dc54802d512a5d891a35c1663392caryclark setUpWinding(start, end, &maxWinding, sumWinding); 1564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool from = maxWinding != 0; 15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool to = *sumWinding != 0; 15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gUnaryActiveEdge[from][to]; 15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 16007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 16227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkvoid SkOpSegment::addAlignIntersection(SkOpPtT& endPtT, SkPoint& oldPt, 16327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkOpContourHead* contourList, SkChunkAlloc* allocator) { 16427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark const SkPoint& newPt = endPtT.fPt; 16527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (newPt == oldPt) { 16627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return; 16727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 16827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkPoint line[2] = { newPt, oldPt }; 16927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkPathOpsBounds lineBounds; 17027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark lineBounds.setBounds(line, 2); 17127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDLine aLine; 17227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark aLine.set(line); 17327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkOpContour* current = contourList; 17427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark do { 17527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (!SkPathOpsBounds::Intersects(current->bounds(), lineBounds)) { 17627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 17727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 17827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkOpSegment* segment = current->first(); 17927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark do { 18027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (!SkPathOpsBounds::Intersects(segment->bounds(), lineBounds)) { 18127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 18227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 18327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (newPt == segment->fPts[0]) { 18427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 18527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 18627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (newPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { 18727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 18827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 18927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (oldPt == segment->fPts[0]) { 19027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 19127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 19227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (oldPt == segment->fPts[SkPathOpsVerbToPoints(segment->fVerb)]) { 19327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 19427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 19527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (endPtT.contains(segment)) { 19627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark continue; 19727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 19827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkIntersections i; 19927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark switch (segment->fVerb) { 20027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark case SkPath::kLine_Verb: { 20127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDLine bLine; 20227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark bLine.set(segment->fPts); 20327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark i.intersect(bLine, aLine); 20427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } break; 20527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark case SkPath::kQuad_Verb: { 20627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDQuad bQuad; 20727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark bQuad.set(segment->fPts); 20827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark i.intersect(bQuad, aLine); 20927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } break; 21027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark case SkPath::kConic_Verb: { 21127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDConic bConic; 21227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark bConic.set(segment->fPts, segment->fWeight); 21327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark i.intersect(bConic, aLine); 21427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } break; 21527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark case SkPath::kCubic_Verb: { 21627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDCubic bCubic; 21727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark bCubic.set(segment->fPts); 21827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark i.intersect(bCubic, aLine); 21927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } break; 22027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark default: 22127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkASSERT(0); 22227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 22327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (i.used()) { 22427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkASSERT(i.used() == 1); 22527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkASSERT(!zero_or_one(i[0][0])); 22627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkOpSpanBase* checkSpan = fHead.next(); 22727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark while (!checkSpan->final()) { 22827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (checkSpan->contains(segment)) { 22927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark goto nextSegment; 23027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 23127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark checkSpan = checkSpan->upCast()->next(); 23227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 23327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkOpPtT* ptT = segment->addT(i[0][0], SkOpSegment::kAllowAlias, allocator); 23427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark ptT->fPt = newPt; 23527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark endPtT.addOpp(ptT); 23627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 23727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark nextSegment: 23827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark ; 23927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } while ((segment = segment->next())); 24027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } while ((current = current->next())); 24127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 24227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 243ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkbool SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, 244ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark SkPathWriter* path) const { 245ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark if (start->starter(end)->alreadyAdded()) { 246ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark return false; 247ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark } 2481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkOpCurve edge; 24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkPoint* ePtr; 2501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkScalar eWeight; 25154359294a7c9dc54802d512a5d891a35c1663392caryclark if ((start == &fHead && end == &fTail) || (start == &fTail && end == &fHead)) { 25207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ePtr = fPts; 2531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark eWeight = fWeight; 25407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 25507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZE? if not active, skip remainder and return xyAtT(end) 2561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark subDivide(start, end, &edge); 2571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark ePtr = edge.fPts; 2581049f1246e7be4ccb68001361efceb8933e6f81ccaryclark eWeight = edge.fWeight; 25907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 260ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark bool reverse = ePtr == fPts && start != &fHead; 261ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark if (reverse) { 262ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]); 263ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark switch (fVerb) { 264ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kLine_Verb: 265ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->deferredLine(ePtr[0]); 266ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 267ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kQuad_Verb: 268ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->quadTo(ePtr[1], ePtr[0]); 269ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 270ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kConic_Verb: 271ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->conicTo(ePtr[1], ePtr[0], eWeight); 272ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 273ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kCubic_Verb: 274ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->cubicTo(ePtr[2], ePtr[1], ePtr[0]); 275ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 276ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark default: 277ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark SkASSERT(0); 278ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark } 279ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark } else { 280ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->deferredMoveLine(ePtr[0]); 281ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark switch (fVerb) { 282ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kLine_Verb: 283ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->deferredLine(ePtr[1]); 284ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 285ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kQuad_Verb: 286ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->quadTo(ePtr[1], ePtr[2]); 287ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 288ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kConic_Verb: 289ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->conicTo(ePtr[1], ePtr[2], eWeight); 290ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 291ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark case SkPath::kCubic_Verb: 292ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); 293ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark break; 294ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark default: 295ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark SkASSERT(0); 29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 298ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark return true; 29907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 30007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 30154359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* allocator) { 30296fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpanBase* existing = nullptr; 30354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* test = &fHead; 30454359294a7c9dc54802d512a5d891a35c1663392caryclark double testT; 3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 30654359294a7c9dc54802d512a5d891a35c1663392caryclark if ((testT = test->ptT()->fT) >= t) { 30754359294a7c9dc54802d512a5d891a35c1663392caryclark if (testT == t) { 30854359294a7c9dc54802d512a5d891a35c1663392caryclark existing = test; 30954359294a7c9dc54802d512a5d891a35c1663392caryclark } 31054359294a7c9dc54802d512a5d891a35c1663392caryclark break; 31154359294a7c9dc54802d512a5d891a35c1663392caryclark } 31254359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((test = test->upCast()->next())); 31354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* result; 31454359294a7c9dc54802d512a5d891a35c1663392caryclark if (existing && existing->contains(opp)) { 31554359294a7c9dc54802d512a5d891a35c1663392caryclark result = existing->ptT(); 31654359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 31754359294a7c9dc54802d512a5d891a35c1663392caryclark result = this->addT(t, SkOpSegment::kNoAlias, allocator); 31807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 31954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(result); 32054359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 32107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 32207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 32354359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpSegment::addT(double t, AllowAlias allowAlias, SkChunkAlloc* allocator) { 32454359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 32554359294a7c9dc54802d512a5d891a35c1663392caryclark SkPoint pt = this->ptAtT(t); 32654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* span = &fHead; 3274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 32854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* result = span->ptT(); 32908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* loop; 33008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark bool duplicatePt; 33154359294a7c9dc54802d512a5d891a35c1663392caryclark if (t == result->fT) { 33208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto bumpSpan; 33354359294a7c9dc54802d512a5d891a35c1663392caryclark } 33454359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->match(result, this, t, pt)) { 33554359294a7c9dc54802d512a5d891a35c1663392caryclark // see if any existing alias matches segment, pt, and t 33608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark loop = result->next(); 33708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark duplicatePt = false; 33854359294a7c9dc54802d512a5d891a35c1663392caryclark while (loop != result) { 33954359294a7c9dc54802d512a5d891a35c1663392caryclark bool ptMatch = loop->fPt == pt; 34054359294a7c9dc54802d512a5d891a35c1663392caryclark if (loop->segment() == this && loop->fT == t && ptMatch) { 34108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto bumpSpan; 34254359294a7c9dc54802d512a5d891a35c1663392caryclark } 34354359294a7c9dc54802d512a5d891a35c1663392caryclark duplicatePt |= ptMatch; 34454359294a7c9dc54802d512a5d891a35c1663392caryclark loop = loop->next(); 34554359294a7c9dc54802d512a5d891a35c1663392caryclark } 34654359294a7c9dc54802d512a5d891a35c1663392caryclark if (kNoAlias == allowAlias) { 34708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark bumpSpan: 34808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark span->bumpSpanAdds(); 34954359294a7c9dc54802d512a5d891a35c1663392caryclark return result; 35054359294a7c9dc54802d512a5d891a35c1663392caryclark } 35154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* alias = SkOpTAllocator<SkOpPtT>::Allocate(allocator); 35254359294a7c9dc54802d512a5d891a35c1663392caryclark alias->init(result->span(), t, pt, duplicatePt); 35354359294a7c9dc54802d512a5d891a35c1663392caryclark result->insert(alias); 35454359294a7c9dc54802d512a5d891a35c1663392caryclark result->span()->unaligned(); 35554359294a7c9dc54802d512a5d891a35c1663392caryclark this->debugValidate(); 35654359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ADD_T 35754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s alias t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 35854359294a7c9dc54802d512a5d891a35c1663392caryclark alias->segment()->debugID(), alias->span()->debugID()); 35954359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 36008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark span->bumpSpanAdds(); 36154359294a7c9dc54802d512a5d891a35c1663392caryclark return alias; 36254359294a7c9dc54802d512a5d891a35c1663392caryclark } 36354359294a7c9dc54802d512a5d891a35c1663392caryclark if (t < result->fT) { 36454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* prev = result->span()->prev(); 365a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark if (!prev) { 366a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark return nullptr; 367a3375e4251c4b2cbf0b5bbdcebfe911914496881caryclark } 36854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = insert(prev, allocator); 36954359294a7c9dc54802d512a5d891a35c1663392caryclark span->init(this, prev, t, pt); 37054359294a7c9dc54802d512a5d891a35c1663392caryclark this->debugValidate(); 37154359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_ADD_T 37254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s insert t=%1.9g segID=%d spanID=%d\n", __FUNCTION__, t, 37354359294a7c9dc54802d512a5d891a35c1663392caryclark span->segment()->debugID(), span->debugID()); 37454359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 37508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark span->bumpSpanAdds(); 37654359294a7c9dc54802d512a5d891a35c1663392caryclark return span->ptT(); 37754359294a7c9dc54802d512a5d891a35c1663392caryclark } 37854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span != &fTail); 37954359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->upCast()->next())); 38054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(0); 38196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 3824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 3834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 38454359294a7c9dc54802d512a5d891a35c1663392caryclark// choose a solitary t and pt value; remove aliases; align the opposite ends 38554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::align() { 38654359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 38754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* span = &fHead; 38854359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->aligned()) { 38954359294a7c9dc54802d512a5d891a35c1663392caryclark span->alignEnd(0, fPts[0]); 39054359294a7c9dc54802d512a5d891a35c1663392caryclark } 39154359294a7c9dc54802d512a5d891a35c1663392caryclark while ((span = span->upCast()->next())) { 39254359294a7c9dc54802d512a5d891a35c1663392caryclark if (span == &fTail) { 39307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 39554359294a7c9dc54802d512a5d891a35c1663392caryclark span->align(); 39607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 39754359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->aligned()) { 39854359294a7c9dc54802d512a5d891a35c1663392caryclark span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]); 39907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 400bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (this->collapsed()) { 401bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpan* span = &fHead; 402bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark do { 403bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark span->setWindValue(0); 404bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark span->setOppValue(0); 405bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark this->markDone(span); 406bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } while ((span = span->next()->upCastable())); 407bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } 40854359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 40954359294a7c9dc54802d512a5d891a35c1663392caryclark} 41054359294a7c9dc54802d512a5d891a35c1663392caryclark 41154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::calcAngles(SkChunkAlloc* allocator) { 41254359294a7c9dc54802d512a5d891a35c1663392caryclark bool activePrior = !fHead.isCanceled(); 41354359294a7c9dc54802d512a5d891a35c1663392caryclark if (activePrior && !fHead.simple()) { 41454359294a7c9dc54802d512a5d891a35c1663392caryclark addStartSpan(allocator); 4150dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 41654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* prior = &fHead; 41754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* spanBase = fHead.next(); 41854359294a7c9dc54802d512a5d891a35c1663392caryclark while (spanBase != &fTail) { 41954359294a7c9dc54802d512a5d891a35c1663392caryclark if (activePrior) { 42054359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* priorAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 42154359294a7c9dc54802d512a5d891a35c1663392caryclark priorAngle->set(spanBase, prior); 42254359294a7c9dc54802d512a5d891a35c1663392caryclark spanBase->setFromAngle(priorAngle); 423ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 42454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = spanBase->upCast(); 42554359294a7c9dc54802d512a5d891a35c1663392caryclark bool active = !span->isCanceled(); 42654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* next = span->next(); 42754359294a7c9dc54802d512a5d891a35c1663392caryclark if (active) { 42854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); 42954359294a7c9dc54802d512a5d891a35c1663392caryclark angle->set(span, next); 43054359294a7c9dc54802d512a5d891a35c1663392caryclark span->setToAngle(angle); 43154359294a7c9dc54802d512a5d891a35c1663392caryclark } 43254359294a7c9dc54802d512a5d891a35c1663392caryclark activePrior = active; 43354359294a7c9dc54802d512a5d891a35c1663392caryclark prior = span; 43454359294a7c9dc54802d512a5d891a35c1663392caryclark spanBase = next; 4354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 43654359294a7c9dc54802d512a5d891a35c1663392caryclark if (activePrior && !fTail.simple()) { 43754359294a7c9dc54802d512a5d891a35c1663392caryclark addEndSpan(allocator); 4384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 43965f553182ab7069378ef863d30094d0327f178d0caryclark} 44065f553182ab7069378ef863d30094d0327f178d0caryclark 441bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclarkbool SkOpSegment::collapsed() const { 442bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt(); 443bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark} 444bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark 44554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 44654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle::IncludeType includeType) { 447624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSegment* baseSegment = baseAngle->segment(); 44854359294a7c9dc54802d512a5d891a35c1663392caryclark int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 44954359294a7c9dc54802d512a5d891a35c1663392caryclark int sumSuWinding; 45054359294a7c9dc54802d512a5d891a35c1663392caryclark bool binary = includeType >= SkOpAngle::kBinarySingle; 45154359294a7c9dc54802d512a5d891a35c1663392caryclark if (binary) { 45254359294a7c9dc54802d512a5d891a35c1663392caryclark sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); 45354359294a7c9dc54802d512a5d891a35c1663392caryclark if (baseSegment->operand()) { 45454359294a7c9dc54802d512a5d891a35c1663392caryclark SkTSwap<int>(sumMiWinding, sumSuWinding); 4550dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 45654359294a7c9dc54802d512a5d891a35c1663392caryclark } 45754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* nextSegment = nextAngle->segment(); 45854359294a7c9dc54802d512a5d891a35c1663392caryclark int maxWinding, sumWinding; 45954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* last; 46054359294a7c9dc54802d512a5d891a35c1663392caryclark if (binary) { 46154359294a7c9dc54802d512a5d891a35c1663392caryclark int oppMaxWinding, oppSumWinding; 46254359294a7c9dc54802d512a5d891a35c1663392caryclark nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 46354359294a7c9dc54802d512a5d891a35c1663392caryclark &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 46454359294a7c9dc54802d512a5d891a35c1663392caryclark last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 46554359294a7c9dc54802d512a5d891a35c1663392caryclark nextAngle); 4664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 46754359294a7c9dc54802d512a5d891a35c1663392caryclark nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 46854359294a7c9dc54802d512a5d891a35c1663392caryclark &maxWinding, &sumWinding); 46954359294a7c9dc54802d512a5d891a35c1663392caryclark last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 4704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 47154359294a7c9dc54802d512a5d891a35c1663392caryclark nextAngle->setLastMarked(last); 4724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 474624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpSegment::ComputeOneSumReverse(SkOpAngle* baseAngle, SkOpAngle* nextAngle, 47554359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle::IncludeType includeType) { 476624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSegment* baseSegment = baseAngle->segment(); 47754359294a7c9dc54802d512a5d891a35c1663392caryclark int sumMiWinding = baseSegment->updateWinding(baseAngle); 47854359294a7c9dc54802d512a5d891a35c1663392caryclark int sumSuWinding; 47954359294a7c9dc54802d512a5d891a35c1663392caryclark bool binary = includeType >= SkOpAngle::kBinarySingle; 4800dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed if (binary) { 48154359294a7c9dc54802d512a5d891a35c1663392caryclark sumSuWinding = baseSegment->updateOppWinding(baseAngle); 48254359294a7c9dc54802d512a5d891a35c1663392caryclark if (baseSegment->operand()) { 48354359294a7c9dc54802d512a5d891a35c1663392caryclark SkTSwap<int>(sumMiWinding, sumSuWinding); 4840dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 4850dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 48654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* nextSegment = nextAngle->segment(); 48754359294a7c9dc54802d512a5d891a35c1663392caryclark int maxWinding, sumWinding; 48854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* last; 48954359294a7c9dc54802d512a5d891a35c1663392caryclark if (binary) { 49054359294a7c9dc54802d512a5d891a35c1663392caryclark int oppMaxWinding, oppSumWinding; 49154359294a7c9dc54802d512a5d891a35c1663392caryclark nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 49254359294a7c9dc54802d512a5d891a35c1663392caryclark &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 49354359294a7c9dc54802d512a5d891a35c1663392caryclark last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 49454359294a7c9dc54802d512a5d891a35c1663392caryclark nextAngle); 4954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 49654359294a7c9dc54802d512a5d891a35c1663392caryclark nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 49754359294a7c9dc54802d512a5d891a35c1663392caryclark &maxWinding, &sumWinding); 49854359294a7c9dc54802d512a5d891a35c1663392caryclark last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 4990dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 50054359294a7c9dc54802d512a5d891a35c1663392caryclark nextAngle->setLastMarked(last); 5014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 503dac1d17027dcaa5596885a9f333979418b35001ccaryclark// at this point, the span is already ordered, or unorderable 50454359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end, 50554359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle::IncludeType includeType) { 5064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(includeType != SkOpAngle::kUnaryXor); 50754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* firstAngle = this->spanToAngle(end, start); 50896fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == firstAngle || nullptr == firstAngle->next()) { 5094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return SK_NaN32; 510570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 511570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // if all angles have a computed winding, 512570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if no adjacent angles are orderable, 513570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if adjacent orderable angles have no computed winding, 514570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // there's nothing to do 515dac1d17027dcaa5596885a9f333979418b35001ccaryclark // if two orderable angles are adjacent, and both are next to orderable angles, 516dac1d17027dcaa5596885a9f333979418b35001ccaryclark // and one has winding computed, transfer to the other 51796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* baseAngle = nullptr; 518570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool tryReverse = false; 519570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // look for counterclockwise transfers 520dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle = firstAngle->previous(); 521dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* next = angle->next(); 522dac1d17027dcaa5596885a9f333979418b35001ccaryclark firstAngle = next; 52307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 524dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = angle; 525dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = next; 526dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 527dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 528dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(angle->next() == next); 529dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 53096fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = nullptr; 5314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 5324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 53354359294a7c9dc54802d512a5d891a35c1663392caryclark int testWinding = angle->starter()->windSum(); 534dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (SK_MinS32 != testWinding) { 535dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = angle; 5364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 5374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 5384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 5394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (baseAngle) { 5404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSum(baseAngle, angle, includeType); 54196fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr; 5424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 543dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (next != firstAngle); 54454359294a7c9dc54802d512a5d891a35c1663392caryclark if (baseAngle && SK_MinS32 == firstAngle->starter()->windSum()) { 5454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle = baseAngle; 5464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 5474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 5484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (tryReverse) { 54996fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = nullptr; 550dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = firstAngle; 551570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 552dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = prior; 553dac1d17027dcaa5596885a9f333979418b35001ccaryclark prior = angle->previous(); 554dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 555dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 556dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 55796fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = nullptr; 558dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 559dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 56054359294a7c9dc54802d512a5d891a35c1663392caryclark int testWinding = angle->starter()->windSum(); 5614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (SK_MinS32 != testWinding) { 5624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = angle; 563570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 56407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 565570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (baseAngle) { 5664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSumReverse(baseAngle, angle, includeType); 56796fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = SK_MinS32 != angle->starter()->windSum() ? angle : nullptr; 568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 569dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (prior != firstAngle); 570570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 57154359294a7c9dc54802d512a5d891a35c1663392caryclark return start->starter(end)->windSum(); 57207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 57307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 57454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::detach(const SkOpSpan* span) { 57554359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 57608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark --fDoneCount; 577ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark } 57808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark --fCount; 57908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(fCount >= fDoneCount); 5800dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed} 5810dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed 58226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclarkdouble SkOpSegment::distSq(double t, const SkOpAngle* oppAngle) const { 58354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDPoint testPt = this->dPtAtT(t); 58454359294a7c9dc54802d512a5d891a35c1663392caryclark SkDLine testPerp = {{ testPt, testPt }}; 58554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDVector slope = this->dSlopeAtT(t); 58654359294a7c9dc54802d512a5d891a35c1663392caryclark testPerp[1].fX += slope.fY; 58754359294a7c9dc54802d512a5d891a35c1663392caryclark testPerp[1].fY -= slope.fX; 58854359294a7c9dc54802d512a5d891a35c1663392caryclark SkIntersections i; 58926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark const SkOpSegment* oppSegment = oppAngle->segment(); 5901049f1246e7be4ccb68001361efceb8933e6f81ccaryclark (*CurveIntersectRay[oppSegment->verb()])(oppSegment->pts(), oppSegment->weight(), testPerp, &i); 59154359294a7c9dc54802d512a5d891a35c1663392caryclark double closestDistSq = SK_ScalarInfinity; 59254359294a7c9dc54802d512a5d891a35c1663392caryclark for (int index = 0; index < i.used(); ++index) { 59354359294a7c9dc54802d512a5d891a35c1663392caryclark if (!between(oppAngle->start()->t(), i[0][index], oppAngle->end()->t())) { 59454359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 5950dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 59654359294a7c9dc54802d512a5d891a35c1663392caryclark double testDistSq = testPt.distanceSquared(i.pt(index)); 59754359294a7c9dc54802d512a5d891a35c1663392caryclark if (closestDistSq > testDistSq) { 59854359294a7c9dc54802d512a5d891a35c1663392caryclark closestDistSq = testDistSq; 5990dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 60054359294a7c9dc54802d512a5d891a35c1663392caryclark } 60154359294a7c9dc54802d512a5d891a35c1663392caryclark return closestDistSq; 6024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 6034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 604d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclarkvoid SkOpSegment::findCollapsed() { 605d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark if (fHead.contains(&fTail)) { 606d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark markAllDone(); 607d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark // move start and end to the same point 608d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark fHead.alignEnd(0, fHead.pt()); 609d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark fTail.setAligned(); 610d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark } 611d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark} 612d4349723fac9c0fd4dcf8c275fb7c756bdfdff7bcaryclark 61307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 61407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The M and S variable name parts stand for the operators. 61507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Mi stands for Minuend (see wiki subtraction, analogous to difference) 61607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Su stands for Subtrahend 61707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The Opp variable name part designates that the value is for the Opposite operator. 61807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Opposite values result from combining coincident spans. 61907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 62054359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart, 62154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask) { 62254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* start = *nextStart; 62354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* end = *nextEnd; 62454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != end); 62554359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 62654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 62754359294a7c9dc54802d512a5d891a35c1663392caryclark if (other) { 62807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 62907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 63007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 63107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 63207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 63354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* startSpan = start->starter(end); 63454359294a7c9dc54802d512a5d891a35c1663392caryclark if (startSpan->done()) { 63596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 636cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 63754359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(startSpan); 63854359294a7c9dc54802d512a5d891a35c1663392caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 63907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 64007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 64154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 64254359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear == end); // is this ever not end? 64354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear); 64454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != endNear); 64554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 6464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 64754359294a7c9dc54802d512a5d891a35c1663392caryclark int calcWinding = computeSum(start, endNear, SkOpAngle::kBinaryOpp); 648570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 6494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!sortable) { 6507eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com *unsortable = true; 65154359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 65296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 6537eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 65454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* angle = this->spanToAngle(end, start); 6554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (angle->unorderable()) { 65607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 65754359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 65896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 65907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 6604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 6614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 6624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 66307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 66454359294a7c9dc54802d512a5d891a35c1663392caryclark int sumMiWinding = updateWinding(end, start); 6658cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (sumMiWinding == SK_MinS32) { 6668cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = true; 66754359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 66896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 6698cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 67054359294a7c9dc54802d512a5d891a35c1663392caryclark int sumSuWinding = updateOppWinding(end, start); 67107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 67207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 67307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 6744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 67596fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpAngle* foundAngle = nullptr; 67607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 67707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // iterate through the angle, and compute everyone's winding 67807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 67907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 68007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 68107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 68207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(), 6834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle->end(), op, &sumMiWinding, &sumSuWinding); 68407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 68507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 68607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 68707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 688570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com foundDone = nextSegment->done(nextAngle); 68907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 69007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 69107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 69207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 69307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 694570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 69554359294a7c9dc54802d512a5d891a35c1663392caryclark (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 696570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 69754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* last = nextAngle->lastMarked(); 69807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 6994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 70007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 70107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 70254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 70354359294a7c9dc54802d512a5d891a35c1663392caryclark last->segment()->debugID(), last->debugID()); 70454359294a7c9dc54802d512a5d891a35c1663392caryclark if (!last->final()) { 70554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum=%d", last->upCast()->windSum()); 70654359294a7c9dc54802d512a5d891a35c1663392caryclark } 70754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 70807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 70907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 7104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 71154359294a7c9dc54802d512a5d891a35c1663392caryclark start->segment()->markDone(start->starter(end)); 71207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 71396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 71407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 71507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 71607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 71707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 71807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 71907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 72007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 72107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 72207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 72307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 72407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 72554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpanBase*>* chase, 72654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, bool* unsortable) { 72754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* start = *nextStart; 72854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* end = *nextEnd; 72954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != end); 73054359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 73154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 73254359294a7c9dc54802d512a5d891a35c1663392caryclark if (other) { 73307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 73407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 73507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 73607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 73707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 73854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* startSpan = start->starter(end); 73954359294a7c9dc54802d512a5d891a35c1663392caryclark if (startSpan->done()) { 74096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 741570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 74254359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(startSpan); 74354359294a7c9dc54802d512a5d891a35c1663392caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 74407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 74507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 74654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 74754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear == end); // is this ever not end? 74854359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear); 74954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != endNear); 75054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 7514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 75254359294a7c9dc54802d512a5d891a35c1663392caryclark int calcWinding = computeSum(start, endNear, SkOpAngle::kUnaryWinding); 753570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 75407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!sortable) { 75507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 75654359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 75796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 75854359294a7c9dc54802d512a5d891a35c1663392caryclark } 75954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* angle = this->spanToAngle(end, start); 76054359294a7c9dc54802d512a5d891a35c1663392caryclark if (angle->unorderable()) { 76154359294a7c9dc54802d512a5d891a35c1663392caryclark *unsortable = true; 76254359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 76396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 76407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 7654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 7664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 7674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 76807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 76954359294a7c9dc54802d512a5d891a35c1663392caryclark int sumWinding = updateWinding(end, start); 7704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 77196fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpAngle* foundAngle = nullptr; 77207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 77354359294a7c9dc54802d512a5d891a35c1663392caryclark // iterate through the angle, and compute everyone's winding 77407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 77507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 77607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 77707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 77807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(), 7794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &sumWinding); 78007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 78107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 78207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 78307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 78407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundDone = nextSegment->done(nextAngle); 78507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 78607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 78707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 78807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 78907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 790570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 79154359294a7c9dc54802d512a5d891a35c1663392caryclark (void) nextSegment->markAndChaseDone(nextAngle->start(), nextAngle->end()); 792570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 79354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* last = nextAngle->lastMarked(); 79407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 7954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 79607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 79707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 79854359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s chase.append segment=%d span=%d", __FUNCTION__, 79954359294a7c9dc54802d512a5d891a35c1663392caryclark last->segment()->debugID(), last->debugID()); 80054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!last->final()) { 80154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum=%d", last->upCast()->windSum()); 80254359294a7c9dc54802d512a5d891a35c1663392caryclark } 80354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 80407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 80507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 80754359294a7c9dc54802d512a5d891a35c1663392caryclark start->segment()->markDone(start->starter(end)); 80807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 80996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 81007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 81107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 81207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 81307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 81407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 81507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 81607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 81707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 81807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 81907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 82007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 82154359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, 82254359294a7c9dc54802d512a5d891a35c1663392caryclark bool* unsortable) { 82354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* start = *nextStart; 82454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* end = *nextEnd; 82554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != end); 82654359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 82754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* other = this->isSimple(nextStart, &step); // advances nextStart 82854359294a7c9dc54802d512a5d891a35c1663392caryclark if (other) { 82954359294a7c9dc54802d512a5d891a35c1663392caryclark // mark the smaller of startIndex, endIndex done, and all adjacent 83054359294a7c9dc54802d512a5d891a35c1663392caryclark // spans with the same T value (but not 'other' spans) 83107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 83207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 83307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 83454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* startSpan = start->starter(end); 83554359294a7c9dc54802d512a5d891a35c1663392caryclark if (startSpan->done()) { 83696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 83707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 83854359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(startSpan); 83954359294a7c9dc54802d512a5d891a35c1663392caryclark *nextEnd = step > 0 ? (*nextStart)->upCast()->next() : (*nextStart)->prev(); 84007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 84107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 84254359294a7c9dc54802d512a5d891a35c1663392caryclark SkDEBUGCODE(SkOpSpanBase* endNear = step > 0 ? (*nextStart)->upCast()->next() \ 84354359294a7c9dc54802d512a5d891a35c1663392caryclark : (*nextStart)->prev()); 84454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear == end); // is this ever not end? 84554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endNear); 84654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(start != endNear); 84754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT((start->t() < endNear->t()) ^ (step < 0)); 84854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* angle = this->spanToAngle(end, start); 84927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (!angle || angle->unorderable()) { 85054359294a7c9dc54802d512a5d891a35c1663392caryclark *unsortable = true; 85154359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(start->starter(end)); 85296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 85354359294a7c9dc54802d512a5d891a35c1663392caryclark } 8544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 8554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 8564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 857570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 8584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 85996fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkOpAngle* foundAngle = nullptr; 86007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 86154359294a7c9dc54802d512a5d891a35c1663392caryclark // iterate through the angle, and compute everyone's winding 86207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 86307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 86407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 86507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 86607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 86707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 86807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 8694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!(foundDone = nextSegment->done(nextAngle))) { 8704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 8714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 87207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle = nextAngle->next(); 8744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (nextAngle != angle); 87554359294a7c9dc54802d512a5d891a35c1663392caryclark start->segment()->markDone(start->starter(end)); 87607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 87796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 87807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 87907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 88007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 88107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 88207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 88307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 88407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 88507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 88607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 88707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 88807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 88954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpGlobalState* SkOpSegment::globalState() const { 89054359294a7c9dc54802d512a5d891a35c1663392caryclark return contour()->globalState(); 89165f553182ab7069378ef863d30094d0327f178d0caryclark} 89265f553182ab7069378ef863d30094d0327f178d0caryclark 8931049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkPath::Verb verb) { 89454359294a7c9dc54802d512a5d891a35c1663392caryclark fContour = contour; 89596fcdcc219d2a0d3579719b84b28bede76efba64halcanary fNext = nullptr; 89627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark fOriginal[0] = pts[0]; 89727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark fOriginal[1] = pts[SkPathOpsVerbToPoints(verb)]; 89807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fPts = pts; 8991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark fWeight = weight; 90007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fVerb = verb; 90154359294a7c9dc54802d512a5d891a35c1663392caryclark fCount = 0; 90254359294a7c9dc54802d512a5d891a35c1663392caryclark fDoneCount = 0; 90354359294a7c9dc54802d512a5d891a35c1663392caryclark fVisited = false; 90454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* zeroSpan = &fHead; 90596fcdcc219d2a0d3579719b84b28bede76efba64halcanary zeroSpan->init(this, nullptr, 0, fPts[0]); 90654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* oneSpan = &fTail; 90754359294a7c9dc54802d512a5d891a35c1663392caryclark zeroSpan->setNext(oneSpan); 90854359294a7c9dc54802d512a5d891a35c1663392caryclark oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]); 9091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGCODE(fID = globalState()->nextSegmentID()); 91054359294a7c9dc54802d512a5d891a35c1663392caryclark} 91154359294a7c9dc54802d512a5d891a35c1663392caryclark 91254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::isClose(double t, const SkOpSegment* opp) const { 91354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDPoint cPt = this->dPtAtT(t); 9141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDVector dxdy = (*CurveDSlopeAtT[this->verb()])(this->pts(), this->weight(), t); 91554359294a7c9dc54802d512a5d891a35c1663392caryclark SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; 91654359294a7c9dc54802d512a5d891a35c1663392caryclark SkIntersections i; 9171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), perp, &i); 91854359294a7c9dc54802d512a5d891a35c1663392caryclark int used = i.used(); 91954359294a7c9dc54802d512a5d891a35c1663392caryclark for (int index = 0; index < used; ++index) { 92054359294a7c9dc54802d512a5d891a35c1663392caryclark if (cPt.roughlyEqual(i.pt(index))) { 9210dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed return true; 9220dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 92354359294a7c9dc54802d512a5d891a35c1663392caryclark } 924a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 925a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 926a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 92754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::isXor() const { 92854359294a7c9dc54802d512a5d891a35c1663392caryclark return fContour->isXor(); 92907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 93007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 9315b5ddd73b4baf22752924bf20d097e96236c36f8caryclarkvoid SkOpSegment::markAllDone() { 9325b5ddd73b4baf22752924bf20d097e96236c36f8caryclark SkOpSpan* span = this->head(); 9335b5ddd73b4baf22752924bf20d097e96236c36f8caryclark do { 9345b5ddd73b4baf22752924bf20d097e96236c36f8caryclark this->markDone(span); 9355b5ddd73b4baf22752924bf20d097e96236c36f8caryclark } while ((span = span->next()->upCastable())); 9365b5ddd73b4baf22752924bf20d097e96236c36f8caryclark} 9375b5ddd73b4baf22752924bf20d097e96236c36f8caryclark 93854359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end) { 93954359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 94054359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* minSpan = start->starter(end); 94154359294a7c9dc54802d512a5d891a35c1663392caryclark markDone(minSpan); 94296fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpanBase* last = nullptr; 94307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 94454359294a7c9dc54802d512a5d891a35c1663392caryclark while ((other = other->nextChase(&start, &step, &minSpan, &last))) { 94507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->done()) { 946dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 947dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 94807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 94954359294a7c9dc54802d512a5d891a35c1663392caryclark other->markDone(minSpan); 95007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 95107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 95207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 95307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 95454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding, 95554359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase** lastPtr) { 95654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* spanStart = start->starter(end); 95754359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 95854359294a7c9dc54802d512a5d891a35c1663392caryclark bool success = markWinding(spanStart, winding); 95996fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpanBase* last = nullptr; 9604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = this; 96154359294a7c9dc54802d512a5d891a35c1663392caryclark while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 96254359294a7c9dc54802d512a5d891a35c1663392caryclark if (spanStart->windSum() != SK_MinS32) { 96354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(spanStart->windSum() == winding); 964dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 965dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 9664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 96754359294a7c9dc54802d512a5d891a35c1663392caryclark (void) other->markWinding(spanStart, winding); 9686f726addf3178b01949bb389ef83cf14a1d7b6b2caryclark } 96965f553182ab7069378ef863d30094d0327f178d0caryclark if (lastPtr) { 97065f553182ab7069378ef863d30094d0327f178d0caryclark *lastPtr = last; 97165f553182ab7069378ef863d30094d0327f178d0caryclark } 97265f553182ab7069378ef863d30094d0327f178d0caryclark return success; 9734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 9744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 97554359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, 97654359294a7c9dc54802d512a5d891a35c1663392caryclark int winding, int oppWinding, SkOpSpanBase** lastPtr) { 97754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* spanStart = start->starter(end); 97854359294a7c9dc54802d512a5d891a35c1663392caryclark int step = start->step(end); 97954359294a7c9dc54802d512a5d891a35c1663392caryclark bool success = markWinding(spanStart, winding, oppWinding); 98096fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpanBase* last = nullptr; 98107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 98254359294a7c9dc54802d512a5d891a35c1663392caryclark while ((other = other->nextChase(&start, &step, &spanStart, &last))) { 98354359294a7c9dc54802d512a5d891a35c1663392caryclark if (spanStart->windSum() != SK_MinS32) { 98454359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->operand() == other->operand()) { 985624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (spanStart->windSum() != winding || spanStart->oppSum() != oppWinding) { 98654359294a7c9dc54802d512a5d891a35c1663392caryclark this->globalState()->setWindingFailed(); 98754359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 988dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 98954359294a7c9dc54802d512a5d891a35c1663392caryclark } else { 99054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(spanStart->windSum() == oppWinding); 99154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(spanStart->oppSum() == winding); 992dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 993dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 994dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 995dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 99654359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->operand() == other->operand()) { 99754359294a7c9dc54802d512a5d891a35c1663392caryclark (void) other->markWinding(spanStart, winding, oppWinding); 998dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 99954359294a7c9dc54802d512a5d891a35c1663392caryclark (void) other->markWinding(spanStart, oppWinding, winding); 100007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 100107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 100265f553182ab7069378ef863d30094d0327f178d0caryclark if (lastPtr) { 100365f553182ab7069378ef863d30094d0327f178d0caryclark *lastPtr = last; 100465f553182ab7069378ef863d30094d0327f178d0caryclark } 100565f553182ab7069378ef863d30094d0327f178d0caryclark return success; 100607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 100707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 100854359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { 100907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 101007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 101107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 101207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 101354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* last; 101454359294a7c9dc54802d512a5d891a35c1663392caryclark (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, &last); 1015570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 1016570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 101754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s last seg=%d span=%d", __FUNCTION__, 101854359294a7c9dc54802d512a5d891a35c1663392caryclark last->segment()->debugID(), last->debugID()); 101954359294a7c9dc54802d512a5d891a35c1663392caryclark if (!last->final()) { 102054359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 102154359294a7c9dc54802d512a5d891a35c1663392caryclark SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 102254359294a7c9dc54802d512a5d891a35c1663392caryclark } 102354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("\n"); 1024570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1025570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 102607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 102707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 102807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 102954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSpanBase* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding, 103054359294a7c9dc54802d512a5d891a35c1663392caryclark int oppSumWinding, const SkOpAngle* angle) { 103107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 103207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 103307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 103407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 103507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { 103607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppMaxWinding = oppSumWinding; 103707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 103896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpanBase* last = nullptr; 103965f553182ab7069378ef863d30094d0327f178d0caryclark // caller doesn't require that this marks anything 104054359294a7c9dc54802d512a5d891a35c1663392caryclark (void) markAndChaseWinding(angle->start(), angle->end(), maxWinding, oppMaxWinding, &last); 1041570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 1042570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 104354359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s last segment=%d span=%d", __FUNCTION__, 104454359294a7c9dc54802d512a5d891a35c1663392caryclark last->segment()->debugID(), last->debugID()); 104554359294a7c9dc54802d512a5d891a35c1663392caryclark if (!last->final()) { 104654359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" windSum="); 104754359294a7c9dc54802d512a5d891a35c1663392caryclark SkPathOpsDebug::WindingPrintf(last->upCast()->windSum()); 104854359294a7c9dc54802d512a5d891a35c1663392caryclark } 104954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf(" \n"); 1050570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1051570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 105207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 105307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 105407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 105554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::markDone(SkOpSpan* span) { 105654359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this == span->segment()); 105754359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 10580dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed return; 10590dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 106054359294a7c9dc54802d512a5d891a35c1663392caryclark#if DEBUG_MARK_DONE 106154359294a7c9dc54802d512a5d891a35c1663392caryclark debugShowNewWinding(__FUNCTION__, span, span->windSum(), span->oppSum()); 106254359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 106354359294a7c9dc54802d512a5d891a35c1663392caryclark span->setDone(true); 106454359294a7c9dc54802d512a5d891a35c1663392caryclark ++fDoneCount; 106554359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 10660dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed} 10670dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed 106854359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding) { 106954359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this == span->segment()); 107054359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(winding); 107154359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 107265f553182ab7069378ef863d30094d0327f178d0caryclark return false; 107307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 107407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 107554359294a7c9dc54802d512a5d891a35c1663392caryclark debugShowNewWinding(__FUNCTION__, span, winding); 10760dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed#endif 107754359294a7c9dc54802d512a5d891a35c1663392caryclark span->setWindSum(winding); 107854359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 107965f553182ab7069378ef863d30094d0327f178d0caryclark return true; 108007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 108107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 108254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::markWinding(SkOpSpan* span, int winding, int oppWinding) { 108354359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(this == span->segment()); 108454359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(winding || oppWinding); 108554359294a7c9dc54802d512a5d891a35c1663392caryclark if (span->done()) { 108665f553182ab7069378ef863d30094d0327f178d0caryclark return false; 108707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 108807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 108954359294a7c9dc54802d512a5d891a35c1663392caryclark debugShowNewWinding(__FUNCTION__, span, winding, oppWinding); 10908cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 109154359294a7c9dc54802d512a5d891a35c1663392caryclark span->setWindSum(winding); 109254359294a7c9dc54802d512a5d891a35c1663392caryclark span->setOppSum(oppWinding); 10934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 109465f553182ab7069378ef863d30094d0327f178d0caryclark return true; 109507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 109607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 109754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::match(const SkOpPtT* base, const SkOpSegment* testParent, double testT, 109854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkPoint& testPt) const { 109954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSegment* baseParent = base->segment(); 110054359294a7c9dc54802d512a5d891a35c1663392caryclark if (this == baseParent && this == testParent && precisely_equal(base->fT, testT)) { 110154359294a7c9dc54802d512a5d891a35c1663392caryclark return true; 110207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 110354359294a7c9dc54802d512a5d891a35c1663392caryclark if (!SkDPoint::ApproximatelyEqual(testPt, base->fPt)) { 110454359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 1105e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 110608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark return !this->ptsDisjoint(base->fT, base->fPt, testT, testPt); 110754359294a7c9dc54802d512a5d891a35c1663392caryclark} 110854359294a7c9dc54802d512a5d891a35c1663392caryclark 110954359294a7c9dc54802d512a5d891a35c1663392caryclarkstatic SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) { 111054359294a7c9dc54802d512a5d891a35c1663392caryclark if (last) { 111154359294a7c9dc54802d512a5d891a35c1663392caryclark *last = endSpan; 111207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 111396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 111407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 111507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 111654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr, 111754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase** last) const { 111854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* origStart = *startPtr; 1119dac1d17027dcaa5596885a9f333979418b35001ccaryclark int step = *stepPtr; 112054359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* endSpan = step > 0 ? origStart->upCast()->next() : origStart->prev(); 112154359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(endSpan); 112254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* angle = step > 0 ? endSpan->fromAngle() : endSpan->upCast()->toAngle(); 112354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* foundSpan; 112454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* otherEnd; 1125dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other; 112696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (angle == nullptr) { 112754359294a7c9dc54802d512a5d891a35c1663392caryclark if (endSpan->t() != 0 && endSpan->t() != 1) { 112896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1129dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 113054359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* otherPtT = endSpan->ptT()->next(); 113154359294a7c9dc54802d512a5d891a35c1663392caryclark other = otherPtT->segment(); 113254359294a7c9dc54802d512a5d891a35c1663392caryclark foundSpan = otherPtT->span(); 113354359294a7c9dc54802d512a5d891a35c1663392caryclark otherEnd = step > 0 ? foundSpan->upCast()->next() : foundSpan->prev(); 1134dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1135dac1d17027dcaa5596885a9f333979418b35001ccaryclark int loopCount = angle->loopCount(); 1136dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (loopCount > 2) { 113754359294a7c9dc54802d512a5d891a35c1663392caryclark return set_last(last, endSpan); 1138dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1139dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpAngle* next = angle->next(); 114096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == next) { 114196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 114265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 1143dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING 1144624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (angle->debugSign() != next->debugSign() && !angle->segment()->contour()->isXor() 114554359294a7c9dc54802d512a5d891a35c1663392caryclark && !next->segment()->contour()->isXor()) { 1146dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s mismatched signs\n", __FUNCTION__); 11470dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 114854359294a7c9dc54802d512a5d891a35c1663392caryclark#endif 1149dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = next->segment(); 115054359294a7c9dc54802d512a5d891a35c1663392caryclark foundSpan = endSpan = next->start(); 1151dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherEnd = next->end(); 1152570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 115354359294a7c9dc54802d512a5d891a35c1663392caryclark int foundStep = foundSpan->step(otherEnd); 1154dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (*stepPtr != foundStep) { 115554359294a7c9dc54802d512a5d891a35c1663392caryclark return set_last(last, endSpan); 115607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 115754359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(*startPtr); 115854359294a7c9dc54802d512a5d891a35c1663392caryclark if (!otherEnd) { 115996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 116065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 116165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// SkASSERT(otherEnd >= 0); 116254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* origMin = step < 0 ? origStart->prev() : origStart->upCast(); 116354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* foundMin = foundSpan->starter(otherEnd); 116454359294a7c9dc54802d512a5d891a35c1663392caryclark if (foundMin->windValue() != origMin->windValue() 116554359294a7c9dc54802d512a5d891a35c1663392caryclark || foundMin->oppValue() != origMin->oppValue()) { 116654359294a7c9dc54802d512a5d891a35c1663392caryclark return set_last(last, endSpan); 1167dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 116854359294a7c9dc54802d512a5d891a35c1663392caryclark *startPtr = foundSpan; 1169dac1d17027dcaa5596885a9f333979418b35001ccaryclark *stepPtr = foundStep; 1170dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (minPtr) { 1171dac1d17027dcaa5596885a9f333979418b35001ccaryclark *minPtr = foundMin; 1172a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 117307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 117407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 117507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1176bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclarkstatic void clear_visited(SkOpSpanBase* span) { 117754359294a7c9dc54802d512a5d891a35c1663392caryclark // reset visited flag back to false 117854359294a7c9dc54802d512a5d891a35c1663392caryclark do { 117954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 118054359294a7c9dc54802d512a5d891a35c1663392caryclark while ((ptT = ptT->next()) != stopPtT) { 118154359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* opp = ptT->segment(); 118254359294a7c9dc54802d512a5d891a35c1663392caryclark opp->resetVisited(); 118307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1184bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } while (!span->final() && (span = span->upCast()->next())); 118507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 118607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 118754359294a7c9dc54802d512a5d891a35c1663392caryclark// look for pairs of undetected coincident curves 118854359294a7c9dc54802d512a5d891a35c1663392caryclark// assumes that segments going in have visited flag clear 118954359294a7c9dc54802d512a5d891a35c1663392caryclark// curve/curve intersection should now do a pretty good job of finding coincident runs so 119054359294a7c9dc54802d512a5d891a35c1663392caryclark// this may be only be necessary for line/curve pairs -- so skip unless this is a line and the 119154359294a7c9dc54802d512a5d891a35c1663392caryclark// the opp is not a line 119227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator) { 119354359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->verb() != SkPath::kLine_Verb) { 119427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 119554359294a7c9dc54802d512a5d891a35c1663392caryclark } 1196bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (this->done()) { 119727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 1198bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } 119996fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSpan* prior = nullptr; 1200bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpanBase* spanBase = &fHead; 120154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 1202bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT; 1203bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkASSERT(ptT->span() == spanBase); 120454359294a7c9dc54802d512a5d891a35c1663392caryclark while ((ptT = ptT->next()) != spanStopPtT) { 1205182b499cd75c971f85cdf52c1827b3c220cc9011caryclark if (ptT->deleted()) { 1206182b499cd75c971f85cdf52c1827b3c220cc9011caryclark continue; 1207182b499cd75c971f85cdf52c1827b3c220cc9011caryclark } 120854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* opp = ptT->span()->segment(); 120926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// if (opp->verb() == SkPath::kLine_Verb) { 121026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// continue; 121126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark// } 1212bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (opp->done()) { 121354359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 121454359294a7c9dc54802d512a5d891a35c1663392caryclark } 1215bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence 1216bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (!opp->visited()) { 121754359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 121854359294a7c9dc54802d512a5d891a35c1663392caryclark } 1219bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (spanBase == &fHead) { 122054359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 1221bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } 1222bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpan* span = spanBase->upCastable(); 1223bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark // FIXME?: this assumes that if the opposite segment is coincident then no more 1224bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark // coincidence needs to be detected. This may not be true. 1225bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (span && span->containsCoincidence(opp)) { 122654359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 122754359294a7c9dc54802d512a5d891a35c1663392caryclark } 122826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (spanBase->segment() == opp) { 122926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 123026ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 1231bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark if (spanBase->containsCoinEnd(opp)) { 1232bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark continue; 1233bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } 123496fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpPtT* priorPtT = nullptr, * priorStopPtT; 123554359294a7c9dc54802d512a5d891a35c1663392caryclark // find prior span containing opp segment 123696fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpSegment* priorOpp = nullptr; 1237bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpSpan* priorTest = spanBase->prev(); 1238bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark while (!priorOpp && priorTest) { 1239bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark priorStopPtT = priorPtT = priorTest->ptT(); 124054359294a7c9dc54802d512a5d891a35c1663392caryclark while ((priorPtT = priorPtT->next()) != priorStopPtT) { 1241182b499cd75c971f85cdf52c1827b3c220cc9011caryclark if (priorPtT->deleted()) { 1242182b499cd75c971f85cdf52c1827b3c220cc9011caryclark continue; 1243182b499cd75c971f85cdf52c1827b3c220cc9011caryclark } 124454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSegment* segment = priorPtT->span()->segment(); 124554359294a7c9dc54802d512a5d891a35c1663392caryclark if (segment == opp) { 1246bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark prior = priorTest; 124754359294a7c9dc54802d512a5d891a35c1663392caryclark priorOpp = opp; 124854359294a7c9dc54802d512a5d891a35c1663392caryclark break; 124954359294a7c9dc54802d512a5d891a35c1663392caryclark } 125054359294a7c9dc54802d512a5d891a35c1663392caryclark } 1251bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark priorTest = priorTest->prev(); 125254359294a7c9dc54802d512a5d891a35c1663392caryclark } 125354359294a7c9dc54802d512a5d891a35c1663392caryclark if (!priorOpp) { 125454359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 125554359294a7c9dc54802d512a5d891a35c1663392caryclark } 125626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (priorPtT == ptT) { 125726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark continue; 125826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 125954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* oppStart = prior->ptT(); 1260bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark SkOpPtT* oppEnd = spanBase->ptT(); 126154359294a7c9dc54802d512a5d891a35c1663392caryclark bool swapped = priorPtT->fT > ptT->fT; 126254359294a7c9dc54802d512a5d891a35c1663392caryclark if (swapped) { 126354359294a7c9dc54802d512a5d891a35c1663392caryclark SkTSwap(priorPtT, ptT); 126454359294a7c9dc54802d512a5d891a35c1663392caryclark SkTSwap(oppStart, oppEnd); 126554359294a7c9dc54802d512a5d891a35c1663392caryclark } 126654359294a7c9dc54802d512a5d891a35c1663392caryclark bool flipped = oppStart->fT > oppEnd->fT; 126726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark bool coincident = false; 126854359294a7c9dc54802d512a5d891a35c1663392caryclark if (coincidences->contains(priorPtT, ptT, oppStart, oppEnd, flipped)) { 126954359294a7c9dc54802d512a5d891a35c1663392caryclark goto swapBack; 127054359294a7c9dc54802d512a5d891a35c1663392caryclark } 127126ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (opp->verb() == SkPath::kLine_Verb) { 127226ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincident = (SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppStart->fPt) || 127326ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::ApproximatelyEqual(priorPtT->fPt, oppEnd->fPt)) && 127426ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark (SkDPoint::ApproximatelyEqual(ptT->fPt, oppStart->fPt) || 127526ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark SkDPoint::ApproximatelyEqual(ptT->fPt, oppEnd->fPt)); 127626ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 127726ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark if (!coincident) { 127826ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark coincident = testForCoincidence(priorPtT, ptT, prior, spanBase, opp, 5000); 127926ad22ab61539e3d3b6bc5e0da8dcebbd52a53decaryclark } 128054359294a7c9dc54802d512a5d891a35c1663392caryclark if (coincident) { 128154359294a7c9dc54802d512a5d891a35c1663392caryclark // mark coincidence 1282182b499cd75c971f85cdf52c1827b3c220cc9011caryclark if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd) 1283182b499cd75c971f85cdf52c1827b3c220cc9011caryclark && !coincidences->extend(oppStart, oppEnd, priorPtT, ptT)) { 1284bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator); 1285bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark } 128654359294a7c9dc54802d512a5d891a35c1663392caryclark clear_visited(&fHead); 128727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return true; 128854359294a7c9dc54802d512a5d891a35c1663392caryclark } 128954359294a7c9dc54802d512a5d891a35c1663392caryclark swapBack: 129054359294a7c9dc54802d512a5d891a35c1663392caryclark if (swapped) { 129154359294a7c9dc54802d512a5d891a35c1663392caryclark SkTSwap(priorPtT, ptT); 129254359294a7c9dc54802d512a5d891a35c1663392caryclark } 12930dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 129496fcdcc219d2a0d3579719b84b28bede76efba64halcanary } while ((spanBase = spanBase->final() ? nullptr : spanBase->upCast()->next())); 129554359294a7c9dc54802d512a5d891a35c1663392caryclark clear_visited(&fHead); 129627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return false; 129754359294a7c9dc54802d512a5d891a35c1663392caryclark} 129854359294a7c9dc54802d512a5d891a35c1663392caryclark 129908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark// if a span has more than one intersection, merge the other segments' span as needed 1300d78c088b6136590371fddd4cab67bfb4bf692fd3caryclarkbool SkOpSegment::moveMultiples() { 130108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark debugValidate(); 130208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* test = &fHead; 130308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark do { 130408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark int addCount = test->spanAddsCount(); 1305d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark if (addCount < 1) { 1306d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark return false; 1307d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark } 130808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (addCount == 1) { 130908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 131008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 131108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* startPtT = test->ptT(); 131208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* testPtT = startPtT; 131308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark do { // iterate through all spans associated with start 131408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppSpan = testPtT->span(); 131508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppSpan->spanAddsCount() == addCount) { 131608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 131708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 131808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppSpan->deleted()) { 131908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 132008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 132108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSegment* oppSegment = oppSpan->segment(); 132208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppSegment == this) { 132308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 132408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 132508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark // find range of spans to consider merging 132608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppPrev = oppSpan; 132708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppFirst = oppSpan; 132808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark while ((oppPrev = oppPrev->prev())) { 132908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (!roughly_equal(oppPrev->t(), oppSpan->t())) { 133008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark break; 133108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 133208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppPrev->spanAddsCount() == addCount) { 133308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 133408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 133508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppPrev->deleted()) { 133608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 133708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 133808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppFirst = oppPrev; 133908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 134008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppNext = oppSpan; 134108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppLast = oppSpan; 134296fcdcc219d2a0d3579719b84b28bede76efba64halcanary while ((oppNext = oppNext->final() ? nullptr : oppNext->upCast()->next())) { 134308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (!roughly_equal(oppNext->t(), oppSpan->t())) { 134408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark break; 134508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 134608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppNext->spanAddsCount() == addCount) { 134708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 134808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 134908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppNext->deleted()) { 135008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 135108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 135208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppLast = oppNext; 135308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 135408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppFirst == oppLast) { 135508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 135608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 135708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSpanBase* oppTest = oppFirst; 135808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark do { 135908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppTest == oppSpan) { 136008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark continue; 136108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 136208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark // check to see if the candidate meets specific criteria: 136308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark // it contains spans of segments in test's loop but not including 'this' 136408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* oppStartPtT = oppTest->ptT(); 136508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* oppPtT = oppStartPtT; 136608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark while ((oppPtT = oppPtT->next()) != oppStartPtT) { 136708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpSegment* oppPtTSegment = oppPtT->segment(); 136808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppPtTSegment == this) { 136908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto tryNextSpan; 137008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 137108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkOpPtT* matchPtT = startPtT; 137208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark do { 137308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (matchPtT->segment() == oppPtTSegment) { 137408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto foundMatch; 137508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 137608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } while ((matchPtT = matchPtT->next()) != startPtT); 137708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto tryNextSpan; 137808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark foundMatch: // merge oppTest and oppSpan 137908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppSegment->debugValidate(); 138008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) { 138108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse 138208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark SkASSERT(oppSpan != &oppSegment->fTail); 138308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppTest->merge(oppSpan->upCast()); 138408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } else { 138508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppSpan->merge(oppTest->upCast()); 138608bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 138708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark oppSegment->debugValidate(); 138808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark goto checkNextSpan; 138908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } 139008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark tryNextSpan: 139108bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark ; 139208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } while (oppTest != oppLast && (oppTest = oppTest->upCast()->next())); 139308bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark } while ((testPtT = testPtT->next()) != startPtT); 139408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclarkcheckNextSpan: 139508bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark ; 139696fcdcc219d2a0d3579719b84b28bede76efba64halcanary } while ((test = test->final() ? nullptr : test->upCast()->next())); 139708bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark debugValidate(); 1398d78c088b6136590371fddd4cab67bfb4bf692fd3caryclark return true; 139908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark} 140008bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark 140154359294a7c9dc54802d512a5d891a35c1663392caryclark// Move nearby t values and pts so they all hang off the same span. Alignment happens later. 140208bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclarkvoid SkOpSegment::moveNearby() { 140354359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 140454359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* spanS = &fHead; 140554359294a7c9dc54802d512a5d891a35c1663392caryclark do { 140654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* test = spanS->upCast()->next(); 140754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* next; 140854359294a7c9dc54802d512a5d891a35c1663392caryclark if (spanS->contains(test)) { 140954359294a7c9dc54802d512a5d891a35c1663392caryclark if (!test->final()) { 141054359294a7c9dc54802d512a5d891a35c1663392caryclark test->upCast()->detach(spanS->ptT()); 141154359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 141254359294a7c9dc54802d512a5d891a35c1663392caryclark } else if (spanS != &fHead) { 141354359294a7c9dc54802d512a5d891a35c1663392caryclark spanS->upCast()->detach(test->ptT()); 141454359294a7c9dc54802d512a5d891a35c1663392caryclark spanS = test; 1415570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 1416570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 141707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 141854359294a7c9dc54802d512a5d891a35c1663392caryclark do { // iterate through all spans associated with start 141954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* startBase = spanS->ptT(); 142096fcdcc219d2a0d3579719b84b28bede76efba64halcanary next = test->final() ? nullptr : test->upCast()->next(); 142154359294a7c9dc54802d512a5d891a35c1663392caryclark do { 142254359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* testBase = test->ptT(); 142354359294a7c9dc54802d512a5d891a35c1663392caryclark do { 142454359294a7c9dc54802d512a5d891a35c1663392caryclark if (startBase == testBase) { 142554359294a7c9dc54802d512a5d891a35c1663392caryclark goto checkNextSpan; 142654359294a7c9dc54802d512a5d891a35c1663392caryclark } 142754359294a7c9dc54802d512a5d891a35c1663392caryclark if (testBase->duplicate()) { 142854359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 142954359294a7c9dc54802d512a5d891a35c1663392caryclark } 143054359294a7c9dc54802d512a5d891a35c1663392caryclark if (this->match(startBase, testBase->segment(), testBase->fT, testBase->fPt)) { 143154359294a7c9dc54802d512a5d891a35c1663392caryclark if (test == &this->fTail) { 143254359294a7c9dc54802d512a5d891a35c1663392caryclark if (spanS == &fHead) { 143354359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 143408bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark return; // if this span has collapsed, remove it from parent 143554359294a7c9dc54802d512a5d891a35c1663392caryclark } 143654359294a7c9dc54802d512a5d891a35c1663392caryclark this->fTail.merge(spanS->upCast()); 143754359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 143808bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark return; 143954359294a7c9dc54802d512a5d891a35c1663392caryclark } 144054359294a7c9dc54802d512a5d891a35c1663392caryclark spanS->merge(test->upCast()); 144154359294a7c9dc54802d512a5d891a35c1663392caryclark goto checkNextSpan; 144254359294a7c9dc54802d512a5d891a35c1663392caryclark } 144354359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((testBase = testBase->next()) != test->ptT()); 144454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((startBase = startBase->next()) != spanS->ptT()); 144554359294a7c9dc54802d512a5d891a35c1663392caryclark checkNextSpan: 144654359294a7c9dc54802d512a5d891a35c1663392caryclark ; 144754359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((test = next)); 144854359294a7c9dc54802d512a5d891a35c1663392caryclark spanS = spanS->upCast()->next(); 144954359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!spanS->final()); 145054359294a7c9dc54802d512a5d891a35c1663392caryclark debugValidate(); 1451dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1452dac1d17027dcaa5596885a9f333979418b35001ccaryclark 145354359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::operand() const { 145454359294a7c9dc54802d512a5d891a35c1663392caryclark return fContour->operand(); 14555e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark} 14565e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark 145754359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::oppXor() const { 145854359294a7c9dc54802d512a5d891a35c1663392caryclark return fContour->oppXor(); 1459ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} 1460ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark 146154359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt2) const { 146254359294a7c9dc54802d512a5d891a35c1663392caryclark if (fVerb == SkPath::kLine_Verb) { 146354359294a7c9dc54802d512a5d891a35c1663392caryclark return false; 14640dc4dd6dda9a7912f696b46d9c02155ec1d1ba5freed } 146554359294a7c9dc54802d512a5d891a35c1663392caryclark // quads (and cubics) can loop back to nearly a line so that an opposite curve 146654359294a7c9dc54802d512a5d891a35c1663392caryclark // hits in two places with very different t values. 146754359294a7c9dc54802d512a5d891a35c1663392caryclark // OPTIMIZATION: curves could be preflighted so that, for example, something like 146854359294a7c9dc54802d512a5d891a35c1663392caryclark // 'controls contained by ends' could avoid this check for common curves 146954359294a7c9dc54802d512a5d891a35c1663392caryclark // 'ends are extremes in x or y' is cheaper to compute and real-world common 147054359294a7c9dc54802d512a5d891a35c1663392caryclark // on the other hand, the below check is relatively inexpensive 147154359294a7c9dc54802d512a5d891a35c1663392caryclark double midT = (t1 + t2) / 2; 147254359294a7c9dc54802d512a5d891a35c1663392caryclark SkPoint midPt = this->ptAtT(midT); 147354359294a7c9dc54802d512a5d891a35c1663392caryclark double seDistSq = SkTMax(pt1.distanceToSqd(pt2) * 2, FLT_EPSILON * 2); 147454359294a7c9dc54802d512a5d891a35c1663392caryclark return midPt.distanceToSqd(pt1) > seDistSq || midPt.distanceToSqd(pt2) > seDistSq; 147554359294a7c9dc54802d512a5d891a35c1663392caryclark} 147654359294a7c9dc54802d512a5d891a35c1663392caryclark 147754359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 147854359294a7c9dc54802d512a5d891a35c1663392caryclark int* maxWinding, int* sumWinding) { 147954359294a7c9dc54802d512a5d891a35c1663392caryclark int deltaSum = SpanSign(start, end); 148054359294a7c9dc54802d512a5d891a35c1663392caryclark *maxWinding = *sumMiWinding; 148154359294a7c9dc54802d512a5d891a35c1663392caryclark *sumWinding = *sumMiWinding -= deltaSum; 148260e0fee6d4acff638ccc9670c4055aced529a7a0bungeman SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 1483dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1484dac1d17027dcaa5596885a9f333979418b35001ccaryclark 148554359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding, 148654359294a7c9dc54802d512a5d891a35c1663392caryclark int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding, 148754359294a7c9dc54802d512a5d891a35c1663392caryclark int* oppSumWinding) { 148854359294a7c9dc54802d512a5d891a35c1663392caryclark int deltaSum = SpanSign(start, end); 148954359294a7c9dc54802d512a5d891a35c1663392caryclark int oppDeltaSum = OppSign(start, end); 149007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 149107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumSuWinding; 149207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumSuWinding -= deltaSum; 149307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumMiWinding; 149407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumMiWinding -= oppDeltaSum; 149507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 149607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumMiWinding; 149707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumMiWinding -= deltaSum; 149807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumSuWinding; 149907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumSuWinding -= oppDeltaSum; 150007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 150160e0fee6d4acff638ccc9670c4055aced529a7a0bungeman SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 150260e0fee6d4acff638ccc9670c4055aced529a7a0bungeman SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM); 150307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 150407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 15054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::sortAngles() { 150654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* span = &this->fHead; 15074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 150854359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* fromAngle = span->fromAngle(); 150996fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkOpAngle* toAngle = span->final() ? nullptr : span->upCast()->toAngle(); 1510dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!fromAngle && !toAngle) { 15114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 15124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1513cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#if DEBUG_ANGLE 15144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool wroteAfterHeader = false; 1515cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#endif 151654359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* baseAngle = fromAngle; 151754359294a7c9dc54802d512a5d891a35c1663392caryclark if (fromAngle && toAngle) { 15184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 151954359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), span->t(), 152054359294a7c9dc54802d512a5d891a35c1663392caryclark span->debugID()); 152154359294a7c9dc54802d512a5d891a35c1663392caryclark wroteAfterHeader = true; 15224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 152354359294a7c9dc54802d512a5d891a35c1663392caryclark fromAngle->insert(toAngle); 152454359294a7c9dc54802d512a5d891a35c1663392caryclark } else if (!fromAngle) { 152554359294a7c9dc54802d512a5d891a35c1663392caryclark baseAngle = toAngle; 152607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 152754359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpPtT* ptT = span->ptT(), * stopPtT = ptT; 15284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 152954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpanBase* oSpan = ptT->span(); 153054359294a7c9dc54802d512a5d891a35c1663392caryclark if (oSpan == span) { 153154359294a7c9dc54802d512a5d891a35c1663392caryclark continue; 153254359294a7c9dc54802d512a5d891a35c1663392caryclark } 153354359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpAngle* oAngle = oSpan->fromAngle(); 1534dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oAngle) { 1535570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_ANGLE 15364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!wroteAfterHeader) { 153754359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 153854359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID()); 15394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org wroteAfterHeader = true; 15404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1541570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 154254359294a7c9dc54802d512a5d891a35c1663392caryclark if (!oAngle->loopContains(baseAngle)) { 15438cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org baseAngle->insert(oAngle); 15448cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 15454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 154654359294a7c9dc54802d512a5d891a35c1663392caryclark if (!oSpan->final()) { 154754359294a7c9dc54802d512a5d891a35c1663392caryclark oAngle = oSpan->upCast()->toAngle(); 154854359294a7c9dc54802d512a5d891a35c1663392caryclark if (oAngle) { 15494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 155054359294a7c9dc54802d512a5d891a35c1663392caryclark if (!wroteAfterHeader) { 155154359294a7c9dc54802d512a5d891a35c1663392caryclark SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), 155254359294a7c9dc54802d512a5d891a35c1663392caryclark span->t(), span->debugID()); 155354359294a7c9dc54802d512a5d891a35c1663392caryclark wroteAfterHeader = true; 155454359294a7c9dc54802d512a5d891a35c1663392caryclark } 15554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 155654359294a7c9dc54802d512a5d891a35c1663392caryclark if (!oAngle->loopContains(baseAngle)) { 155754359294a7c9dc54802d512a5d891a35c1663392caryclark baseAngle->insert(oAngle); 155854359294a7c9dc54802d512a5d891a35c1663392caryclark } 15598cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 15604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 156154359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((ptT = ptT->next()) != stopPtT); 156254359294a7c9dc54802d512a5d891a35c1663392caryclark if (baseAngle->loopCount() == 1) { 156396fcdcc219d2a0d3579719b84b28bede76efba64halcanary span->setFromAngle(nullptr); 156454359294a7c9dc54802d512a5d891a35c1663392caryclark if (toAngle) { 156596fcdcc219d2a0d3579719b84b28bede76efba64halcanary span->upCast()->setToAngle(nullptr); 15664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 156796fcdcc219d2a0d3579719b84b28bede76efba64halcanary baseAngle = nullptr; 15684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 15704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!baseAngle || baseAngle->loopCount() > 1); 15714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 157254359294a7c9dc54802d512a5d891a35c1663392caryclark } while (!span->final() && (span = span->upCast()->next())); 1573570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1574570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1575cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed 157654359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, 15771049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkOpCurve* edge) const { 1578cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 157954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT& startPtT = *start->ptT(); 158054359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT& endPtT = *end->ptT(); 15811049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGCODE(edge->fVerb = fVerb); 15821049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[0] = startPtT.fPt; 1583cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 15841049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[points] = endPtT.fPt; 15851049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fWeight = 1; 1586cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 1587cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1588cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 158954359294a7c9dc54802d512a5d891a35c1663392caryclark double startT = startPtT.fT; 159054359294a7c9dc54802d512a5d891a35c1663392caryclark double endT = endPtT.fT; 1591cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 1592cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 159307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 15941049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = fPts[1]; 15951049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return false; 15961049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 15971049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (fVerb == SkPath::kConic_Verb) { 15981049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = fPts[1]; 15991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fWeight = fWeight; 1600cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 160107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1602cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1603cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (start < end) { 16041049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = fPts[1]; 16051049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[2] = fPts[2]; 1606cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1607cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 16081049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = fPts[2]; 16091049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[2] = fPts[1]; 1610cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1611cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 16121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark const SkDPoint sub[2] = {{ edge->fPts[0].fX, edge->fPts[0].fY}, 16131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark {edge->fPts[points].fX, edge->fPts[points].fY }}; 1614cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 16151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoint(); 16161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else if (fVerb == SkPath::kConic_Verb) { 16171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = SkDConic::SubDivide(fPts, fWeight, sub[0], sub[1], 16181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark startT, endT, &edge->fWeight).asSkPoint(); 1619cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 1620cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 1621cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDPoint ctrl[2]; 1622cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl); 16231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[1] = ctrl[0].asSkPoint(); 16241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fPts[2] = ctrl[1].asSkPoint(); 162507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1626cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 1627cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com} 1628cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 162954359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, 16301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDCurve* edge) const { 1631cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 163254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT& startPtT = *start->ptT(); 163354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpPtT& endPtT = *end->ptT(); 16341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDEBUGCODE(edge->fVerb = fVerb); 16351049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[0].set(startPtT.fPt); 1636cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 16371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[points].set(endPtT.fPt); 1638cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 1639cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1640cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 164154359294a7c9dc54802d512a5d891a35c1663392caryclark double startT = startPtT.fT; 164254359294a7c9dc54802d512a5d891a35c1663392caryclark double endT = endPtT.fT; 1643cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 1644cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 1645cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 16461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fLine[1].set(fPts[1]); 16471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark return false; 16481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } 16491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark if (fVerb == SkPath::kConic_Verb) { 16501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fConic[1].set(fPts[1]); 16511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fConic.fWeight = fWeight; 1652cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1653cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1654cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 165554359294a7c9dc54802d512a5d891a35c1663392caryclark if (startT == 0) { 16561049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[1].set(fPts[1]); 16571049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[2].set(fPts[2]); 1658cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1659cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 16601049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[1].set(fPts[2]); 16611049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fCubic[2].set(fPts[1]); 1662cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 1663cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1664cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 16651049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fQuad[1] = SkDQuad::SubDivide(fPts, edge->fQuad[0], edge->fQuad[2], startT, endT); 16661049f1246e7be4ccb68001361efceb8933e6f81ccaryclark } else if (fVerb == SkPath::kConic_Verb) { 16671049f1246e7be4ccb68001361efceb8933e6f81ccaryclark edge->fConic[1] = SkDConic::SubDivide(fPts, fWeight, edge->fQuad[0], edge->fQuad[2], 16681049f1246e7be4ccb68001361efceb8933e6f81ccaryclark startT, endT, &edge->fConic.fWeight); 1669cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 1670cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 16711049f1246e7be4ccb68001361efceb8933e6f81ccaryclark SkDCubic::SubDivide(fPts, edge->fCubic[0], edge->fCubic[3], startT, endT, &edge->fCubic[1]); 1672cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 1673cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 167407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 167507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 167627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclarkbool SkOpSegment::testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT, 167727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark const SkOpSpanBase* prior, const SkOpSpanBase* spanBase, const SkOpSegment* opp, 167827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkScalar flatnessLimit) const { 167927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark // average t, find mid pt 168027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark double midT = (prior->t() + spanBase->t()) / 2; 168127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkPoint midPt = this->ptAtT(midT); 168227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark bool coincident = true; 168327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark // if the mid pt is not near either end pt, project perpendicular through opp seg 168427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (!SkDPoint::ApproximatelyEqual(priorPtT->fPt, midPt) 168527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark && !SkDPoint::ApproximatelyEqual(ptT->fPt, midPt)) { 168627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark coincident = false; 168727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkIntersections i; 168827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkVector dxdy = (*CurveSlopeAtT[fVerb])(this->pts(), this->weight(), midT); 1689b669300a9753893ef900207c38aeff2d467764e5caryclark SkDLine ray = {{{midPt.fX, midPt.fY}, 1690b669300a9753893ef900207c38aeff2d467764e5caryclark {(double) midPt.fX + dxdy.fY, (double) midPt.fY - dxdy.fX}}}; 169127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark (*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), ray, &i); 169227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark // measure distance and see if it's small enough to denote coincidence 169327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark for (int index = 0; index < i.used(); ++index) { 169427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkDPoint oppPt = i.pt(index); 169527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark if (oppPt.approximatelyEqual(midPt)) { 169627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkVector oppDxdy = (*CurveSlopeAtT[opp->verb()])(opp->pts(), 169727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark opp->weight(), i[index][0]); 169827c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark oppDxdy.normalize(); 169927c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark dxdy.normalize(); 170027c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark SkScalar flatness = SkScalarAbs(dxdy.cross(oppDxdy) / FLT_EPSILON); 170127c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark coincident |= flatness < flatnessLimit; 170227c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 170327c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 170427c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark } 170527c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark return coincident; 170627c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark} 170727c8eb8ffd7e221693d840c2b9279d53fe6f03d4caryclark 170854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { 170954359294a7c9dc54802d512a5d891a35c1663392caryclark SkOpSpan* span = this->head(); 171054359294a7c9dc54802d512a5d891a35c1663392caryclark do { 171154359294a7c9dc54802d512a5d891a35c1663392caryclark if (!span->done()) { 171207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 171307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 171454359294a7c9dc54802d512a5d891a35c1663392caryclark } while ((span = span->next()->upCastable())); 171554359294a7c9dc54802d512a5d891a35c1663392caryclark SkASSERT(span); 171654359294a7c9dc54802d512a5d891a35c1663392caryclark *start = span; 171754359294a7c9dc54802d512a5d891a35c1663392caryclark *end = span->next(); 171807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 171907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 172054359294a7c9dc54802d512a5d891a35c1663392caryclarkint SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { 172154359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* lesser = start->starter(end); 172254359294a7c9dc54802d512a5d891a35c1663392caryclark int oppWinding = lesser->oppSum(); 172354359294a7c9dc54802d512a5d891a35c1663392caryclark int oppSpanWinding = SkOpSegment::OppSign(start, end); 172407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding) 172507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com && oppWinding != SK_MaxS32) { 172607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWinding -= oppSpanWinding; 172707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 172807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return oppWinding; 172907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 173007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 173107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(const SkOpAngle* angle) const { 173254359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* startSpan = angle->start(); 173354359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* endSpan = angle->end(); 173454359294a7c9dc54802d512a5d891a35c1663392caryclark return updateOppWinding(endSpan, startSpan); 173507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 173607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 173707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { 173854359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* startSpan = angle->start(); 173954359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpanBase* endSpan = angle->end(); 174054359294a7c9dc54802d512a5d891a35c1663392caryclark return updateOppWinding(startSpan, endSpan); 174107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 174207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1743624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) { 1744624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSpan* lesser = start->starter(end); 174554359294a7c9dc54802d512a5d891a35c1663392caryclark int winding = lesser->windSum(); 17468cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (winding == SK_MinS32) { 1747bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark winding = lesser->computeWindSum(); 1748624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark } 1749624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark if (winding == SK_MinS32) { 17508cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return winding; 17518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 175254359294a7c9dc54802d512a5d891a35c1663392caryclark int spanWinding = SkOpSegment::SpanSign(start, end); 1753570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (winding && UseInnerWinding(winding - spanWinding, winding) 1754570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && winding != SK_MaxS32) { 175507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com winding -= spanWinding; 175607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 175707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return winding; 175807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 175907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1760624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWinding(SkOpAngle* angle) { 1761624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSpanBase* startSpan = angle->start(); 1762624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSpanBase* endSpan = angle->end(); 176354359294a7c9dc54802d512a5d891a35c1663392caryclark return updateWinding(endSpan, startSpan); 1764570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1765570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1766624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkint SkOpSegment::updateWindingReverse(const SkOpAngle* angle) { 1767624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSpanBase* startSpan = angle->start(); 1768624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark SkOpSpanBase* endSpan = angle->end(); 176954359294a7c9dc54802d512a5d891a35c1663392caryclark return updateWinding(startSpan, endSpan); 1770570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1771570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1772570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// OPTIMIZATION: does the following also work, and is it any faster? 1773570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// return outerWinding * innerWinding > 0 1774570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0))) 1775570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) { 1776570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(outerWinding != SK_MaxS32); 1777570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(innerWinding != SK_MaxS32); 177860e0fee6d4acff638ccc9670c4055aced529a7a0bungeman int absOut = SkTAbs(outerWinding); 177960e0fee6d4acff638ccc9670c4055aced529a7a0bungeman int absIn = SkTAbs(innerWinding); 1780570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; 1781570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return result; 1782570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1783570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 178407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windSum(const SkOpAngle* angle) const { 178554359294a7c9dc54802d512a5d891a35c1663392caryclark const SkOpSpan* minSpan = angle->start()->starter(angle->end()); 178654359294a7c9dc54802d512a5d891a35c1663392caryclark return minSpan->windSum(); 178707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 1788