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 */ 707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkIntersections.h" 8dac1d17027dcaa5596885a9f333979418b35001ccaryclark#include "SkOpContour.h" 907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h" 1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h" 117dfbb0720a133c0f63ac7be504f335bbcc62a291caryclark@google.com#include "SkTSort.h" 1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define F (false) // discard the edge 1407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define T (true) // keep the edge 1507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gUnaryActiveEdge[2][2] = { 1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// from=0 from=1 1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// to=0,1 to=0,1 1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {F, T}, {T, F}, 2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}; 2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = { 2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// miFrom=0 miFrom=1 244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// miTo=0 miTo=1 miTo=0 miTo=1 254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1 2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@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 2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su 2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su 2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su 3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su 3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}; 3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef F 3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#undef T 3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 36570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comenum { 37570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com kOutsideTrackedTCount = 16, // FIXME: determine what this should be 38570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com kMissingSpanCount = 4, // FIXME: determine what this should be 39570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}; 4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpAngle* SkOpSegment::activeAngle(int index, int* start, int* end, bool* done, 424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool* sortable) const { 434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (const SkOpAngle* result = activeAngleInner(index, start, end, done, sortable)) { 444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return result; 4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 46570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double referenceT = fTs[index].fT; 4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 48570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (--lesser >= 0 49570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].fTiny)) { 504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (const SkOpAngle* result = activeAngleOther(lesser, start, end, done, sortable)) { 514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return result; 5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (const SkOpAngle* result = activeAngleOther(index, start, end, done, sortable)) { 564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return result; 5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 58570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (++index == fTs.count()) { 59570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com break; 60570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 61570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (fTs[index - 1].fTiny) { 62570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com referenceT = fTs[index].fT; 63570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 64570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 65570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (precisely_negative(fTs[index].fT - referenceT)); 664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; 6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpAngle* SkOpSegment::activeAngleInner(int index, int* start, int* end, bool* done, 704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool* sortable) const { 7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int next = nextExactSpan(index, 1); 7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (next > 0) { 734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& upSpan = fTs[index]; 7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (upSpan.fWindValue || upSpan.fOppValue) { 754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (*end < 0) { 764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *start = index; 774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *end = next; 7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 798cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (!upSpan.fDone) { 804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (upSpan.fWindSum != SK_MinS32) { 814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return spanToAngle(index, next); 824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(upSpan.fDone); 8707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int prev = nextExactSpan(index, -1); 9007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // edge leading into junction 9107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (prev >= 0) { 924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& downSpan = fTs[prev]; 9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (downSpan.fWindValue || downSpan.fOppValue) { 944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (*end < 0) { 954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *start = index; 964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *end = prev; 974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!downSpan.fDone) { 994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (downSpan.fWindSum != SK_MinS32) { 1004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return spanToAngle(index, prev); 1014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *done = false; 10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 1054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(downSpan.fDone); 10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; 1094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 1104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpAngle* SkOpSegment::activeAngleOther(int index, int* start, int* end, bool* done, 1124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool* sortable) const { 1134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* span = &fTs[index]; 1144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = span->fOther; 1154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oIndex = span->fOtherIndex; 1164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return other->activeAngleInner(oIndex, start, end, done, sortable); 11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1198cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.orgSkPoint SkOpSegment::activeLeftTop(int* firstT) const { 12007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!done()); 12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; 12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int count = fTs.count(); 12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // see if either end is not done since we want smaller Y of the pair 12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool lastDone = true; 12507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double lastT = -1; 12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int index = 0; index < count; ++index) { 12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& span = fTs[index]; 12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (span.fDone && lastDone) { 12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com goto next; 13007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_negative(span.fT - lastT)) { 13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com goto next; 13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com { 13507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkPoint& xy = xyAtT(&span); 13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { 13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com topPt = xy; 13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (firstT) { 13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *firstT = index; 14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 14107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 14207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb != SkPath::kLine_Verb && !lastDone) { 143277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkPoint curveTop = (*CurveTop[SkPathOpsVerbToPoints(fVerb)])(fPts, lastT, span.fT); 14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY 14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com && topPt.fX > curveTop.fX)) { 14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com topPt = curveTop; 14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (firstT) { 14807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *firstT = index; 14907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com lastT = span.fT; 15307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comnext: 15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com lastDone = span.fDone; 15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return topPt; 15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 16007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op) { 16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumMiWinding = updateWinding(endIndex, index); 16207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumSuWinding = updateOppWinding(endIndex, index); 16307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fOperand) { 16407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &sumSuWinding); 16707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 16807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 16907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op, 1704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int* sumMiWinding, int* sumSuWinding) { 1714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; 17207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com setUpWindings(index, endIndex, sumMiWinding, sumSuWinding, 1734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miFrom; 17507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool miTo; 17607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suFrom; 17707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool suTo; 17807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 1794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (oppMaxWinding & xorMiMask) != 0; 1804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (oppSumWinding & xorMiMask) != 0; 1814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (maxWinding & xorSuMask) != 0; 1824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (sumWinding & xorSuMask) != 0; 18307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 1844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miFrom = (maxWinding & xorMiMask) != 0; 1854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org miTo = (sumWinding & xorMiMask) != 0; 1864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suFrom = (oppMaxWinding & xorSuMask) != 0; 1874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org suTo = (oppSumWinding & xorSuMask) != 0; 18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 18907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo]; 19007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ACTIVE_OP 191dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", 192dac1d17027dcaa5596885a9f333979418b35001ccaryclark __FUNCTION__, debugID(), span(index).fT, span(endIndex).fT, 193570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result); 19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 19607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 19707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::activeWinding(int index, int endIndex) { 19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumWinding = updateWinding(endIndex, index); 2004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return activeWinding(index, endIndex, &sumWinding); 20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 2034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgbool SkOpSegment::activeWinding(int index, int endIndex, int* sumWinding) { 2044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int maxWinding; 2054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org setUpWinding(index, endIndex, &maxWinding, sumWinding); 2064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool from = maxWinding != 0; 20707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool to = *sumWinding != 0; 20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool result = gUnaryActiveEdge[from][to]; 20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 212570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, 213570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* other) { 21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int tIndex = -1; 21507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int tCount = fTs.count(); 21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oIndex = -1; 21707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oCount = other->fTs.count(); 21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++tIndex; 220570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (startPt != fTs[tIndex].fPt && tIndex < tCount); 22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int tIndexStart = tIndex; 22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++oIndex; 224570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (endPt != other->fTs[oIndex].fPt && oIndex < oCount); 22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oIndexStart = oIndex; 226570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint* nextPt; 22707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 228570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextPt = &fTs[++tIndex].fPt; 229570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(fTs[tIndex].fT < 1 || startPt != *nextPt); 230570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (startPt == *nextPt); 231570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double nextT = fTs[tIndex].fT; 232570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint* oNextPt; 23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 234570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com oNextPt = &other->fTs[++oIndex].fPt; 235570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(other->fTs[oIndex].fT < 1 || endPt != *oNextPt); 236570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (endPt == *oNextPt); 237570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double oNextT = other->fTs[oIndex].fT; 23807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // at this point, spans before and after are at: 23907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // fTs[tIndexStart - 1], fTs[tIndexStart], fTs[tIndex] 24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if tIndexStart == 0, no prior span 24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if nextT == 1, no following span 24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // advance the span with zero winding 24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if the following span exists (not past the end, non-zero winding) 24507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // connect the two edges 24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!fTs[tIndexStart].fWindValue) { 24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (tIndexStart > 0 && fTs[tIndexStart - 1].fWindValue) { 24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT 24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", 25007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, fID, other->fID, tIndexStart - 1, 25107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fTs[tIndexStart].fT, xyAtT(tIndexStart).fX, 25207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com xyAtT(tIndexStart).fY); 25307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 254bdbb2422b9f20372597367a032d822b4297eab41caryclark SkPoint copy = fTs[tIndexStart].fPt; // add t pair may move the point array 255bdbb2422b9f20372597367a032d822b4297eab41caryclark addTPair(fTs[tIndexStart].fT, other, other->fTs[oIndex].fT, false, copy); 25607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 25707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextT < 1 && fTs[tIndex].fWindValue) { 25807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT 25907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s 2 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", 26007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, fID, other->fID, tIndex, 26107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fTs[tIndex].fT, xyAtT(tIndex).fX, 26207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com xyAtT(tIndex).fY); 26307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 264bdbb2422b9f20372597367a032d822b4297eab41caryclark SkPoint copy = fTs[tIndex].fPt; // add t pair may move the point array 265bdbb2422b9f20372597367a032d822b4297eab41caryclark addTPair(fTs[tIndex].fT, other, other->fTs[oIndexStart].fT, false, copy); 26607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 26807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!other->fTs[oIndexStart].fWindValue); 26907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oIndexStart > 0 && other->fTs[oIndexStart - 1].fWindValue) { 27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT 27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", 27207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, fID, other->fID, oIndexStart - 1, 27307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->fTs[oIndexStart].fT, other->xyAtT(oIndexStart).fX, 27407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->xyAtT(oIndexStart).fY); 27507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->debugAddTPair(other->fTs[oIndexStart].fT, *this, fTs[tIndex].fT); 27607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 27707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 27807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oNextT < 1 && other->fTs[oIndex].fWindValue) { 27907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT 28007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s 4 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", 28107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, fID, other->fID, oIndex, 28207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->fTs[oIndex].fT, other->xyAtT(oIndex).fX, 28307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->xyAtT(oIndex).fY); 28407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->debugAddTPair(other->fTs[oIndex].fT, *this, fTs[tIndexStart].fT); 28507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 28607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 28707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 28807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 28907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 290570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, 291570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* other) { 292570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // walk this to startPt 293570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // walk other to startPt 29407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if either is > 0, add a pointer to the other, copying adjacent winding 29507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int tIndex = -1; 29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oIndex = -1; 29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 29807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++tIndex; 299570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (startPt != fTs[tIndex].fPt); 3004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int ttIndex = tIndex; 3014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool checkOtherTMatch = false; 3024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 3034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& span = fTs[ttIndex]; 3044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (startPt != span.fPt) { 3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 306a1ed7aec95eb8c77d1a39834fea476780007cadeskia.committer@gmail.com } 3074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span.fOther == other && span.fPt == startPt) { 3084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org checkOtherTMatch = true; 3094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 3104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 3114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++ttIndex < count()); 31207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 31307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++oIndex; 314570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (startPt != other->fTs[oIndex].fPt); 3154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool skipAdd = false; 3164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (checkOtherTMatch) { 3174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int ooIndex = oIndex; 3184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 3194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpan = other->fTs[ooIndex]; 3204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (startPt != oSpan.fPt) { 3214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 322a1ed7aec95eb8c77d1a39834fea476780007cadeskia.committer@gmail.com } 3234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oSpan.fT == fTs[ttIndex].fOtherT) { 3244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org skipAdd = true; 3254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 3264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 3274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++ooIndex < other->count()); 3284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 3294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if ((tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) && !skipAdd) { 330570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt); 33107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 332570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkPoint nextPt = startPt; 33307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 334570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint* workPt; 33507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 336570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com workPt = &fTs[++tIndex].fPt; 337570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (nextPt == *workPt); 3388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org const SkPoint* oWorkPt; 33907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 3408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org oWorkPt = &other->fTs[++oIndex].fPt; 3418cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } while (nextPt == *oWorkPt); 342570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextPt = *workPt; 343570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double tStart = fTs[tIndex].fT; 344570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double oStart = other->fTs[oIndex].fT; 34507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (tStart == 1 && oStart == 1 && fOperand == other->fOperand) { 34607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 34707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3488cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (*workPt == *oWorkPt) { 3498cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org addTPair(tStart, other, oStart, false, nextPt); 3508cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 351570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (endPt != nextPt); 35207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 35307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 35407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::addCubic(const SkPoint pts[4], bool operand, bool evenOdd) { 35507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com init(pts, SkPath::kCubic_Verb, operand, evenOdd); 35607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fBounds.setCubicBounds(pts); 35707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 35807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 35907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active) const { 36007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint edge[4]; 36107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkPoint* ePtr; 36207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lastT = fTs.count() - 1; 36307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (lastT < 0 || (start == 0 && end == lastT) || (start == lastT && end == 0)) { 36407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ePtr = fPts; 36507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 36607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZE? if not active, skip remainder and return xyAtT(end) 36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com subDivide(start, end, edge); 36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ePtr = edge; 36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 37007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (active) { 37107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool reverse = ePtr == fPts && start != 0; 37207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (reverse) { 373277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]); 37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com switch (fVerb) { 37507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kLine_Verb: 37607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredLine(ePtr[0]); 37707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 37807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kQuad_Verb: 37907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->quadTo(ePtr[1], ePtr[0]); 38007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 38107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kCubic_Verb: 38207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->cubicTo(ePtr[2], ePtr[1], ePtr[0]); 38307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com default: 38507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(0); 38607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 38707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // return ePtr[0]; 38807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 38907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredMoveLine(ePtr[0]); 39007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com switch (fVerb) { 39107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kLine_Verb: 39207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->deferredLine(ePtr[1]); 39307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 39407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kQuad_Verb: 39507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->quadTo(ePtr[1], ePtr[2]); 39607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 39707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com case SkPath::kCubic_Verb: 39807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com path->cubicTo(ePtr[1], ePtr[2], ePtr[3]); 39907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 40007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com default: 40107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(0); 40207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 40307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 40407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 405277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com // return ePtr[SkPathOpsVerbToPoints(fVerb)]; 40607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 40707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 4084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::addEndSpan(int endIndex) { 40919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(span(endIndex).fT == 1 || (span(endIndex).fTiny 41065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// && approximately_greater_than_one(span(endIndex).fT) 41165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark )); 4124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int spanCount = fTs.count(); 4134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int startIndex = endIndex - 1; 4144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { 41519eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark --startIndex; 41619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(startIndex > 0); 41719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark --endIndex; 4184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 419dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& angle = fAngles.push_back(); 420dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle.set(this, spanCount - 1, startIndex); 4214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 4224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugCheckPointsEqualish(endIndex, spanCount); 4234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 424dac1d17027dcaa5596885a9f333979418b35001ccaryclark setFromAngle(endIndex, &angle); 4254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 427dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::setFromAngle(int endIndex, SkOpAngle* angle) { 4284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int spanCount = fTs.count(); 4294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 430dac1d17027dcaa5596885a9f333979418b35001ccaryclark fTs[endIndex].fFromAngle = angle; 4314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++endIndex < spanCount); 4324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 43407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) { 43507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com init(pts, SkPath::kLine_Verb, operand, evenOdd); 43607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fBounds.set(pts, 2); 43707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 43807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 43907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// add 2 to edge or out of range values to get T extremes 44007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::addOtherT(int index, double otherT, int otherIndex) { 44107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& span = fTs[index]; 4420361032c0b53401030a720bc8b4930c3ec59f19ecaryclark@google.com if (precisely_zero(otherT)) { 44307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com otherT = 0; 4440361032c0b53401030a720bc8b4930c3ec59f19ecaryclark@google.com } else if (precisely_equal(otherT, 1)) { 44507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com otherT = 1; 44607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 44707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span.fOtherT = otherT; 44807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span.fOtherIndex = otherIndex; 44907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 45007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 45107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { 45207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com init(pts, SkPath::kQuad_Verb, operand, evenOdd); 45307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fBounds.setQuadBounds(pts); 45407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 45507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 456dac1d17027dcaa5596885a9f333979418b35001ccaryclarkSkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** anglePtr) { 457dac1d17027dcaa5596885a9f333979418b35001ccaryclark int spanIndex = count() - 1; 458dac1d17027dcaa5596885a9f333979418b35001ccaryclark int startIndex = nextExactSpan(spanIndex, -1); 459dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(startIndex >= 0); 460dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& angle = fAngles.push_back(); 461dac1d17027dcaa5596885a9f333979418b35001ccaryclark *anglePtr = ∠ 462dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle.set(this, spanIndex, startIndex); 463dac1d17027dcaa5596885a9f333979418b35001ccaryclark setFromAngle(spanIndex, &angle); 4644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other; 465dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oStartIndex, oEndIndex; 4664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 467dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = fTs[spanIndex]; 468dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span.fT > 0); 469dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = span.fOther; 470dac1d17027dcaa5596885a9f333979418b35001ccaryclark oStartIndex = span.fOtherIndex; 471dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndIndex = other->nextExactSpan(oStartIndex, 1); 472dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oEndIndex > 0 && other->span(oStartIndex).fWindValue) { 4734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 4744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 475dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndIndex = oStartIndex; 476dac1d17027dcaa5596885a9f333979418b35001ccaryclark oStartIndex = other->nextExactSpan(oEndIndex, -1); 4774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --spanIndex; 478dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (oStartIndex < 0 || !other->span(oStartIndex).fWindSum); 479dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& oAngle = other->fAngles.push_back(); 480dac1d17027dcaa5596885a9f333979418b35001ccaryclark oAngle.set(other, oStartIndex, oEndIndex); 481dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->setToAngle(oEndIndex, &oAngle); 4824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *otherPtr = other; 483dac1d17027dcaa5596885a9f333979418b35001ccaryclark return &oAngle; 4844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 4854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 486dac1d17027dcaa5596885a9f333979418b35001ccaryclarkSkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr) { 487dac1d17027dcaa5596885a9f333979418b35001ccaryclark int endIndex = nextExactSpan(0, 1); 4884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(endIndex > 0); 489dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& angle = fAngles.push_back(); 490dac1d17027dcaa5596885a9f333979418b35001ccaryclark *anglePtr = ∠ 491dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle.set(this, 0, endIndex); 492dac1d17027dcaa5596885a9f333979418b35001ccaryclark setToAngle(endIndex, &angle); 493dac1d17027dcaa5596885a9f333979418b35001ccaryclark int spanIndex = 0; 4944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other; 495dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oStartIndex, oEndIndex; 4964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 497dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = fTs[spanIndex]; 498dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span.fT < 1); 499dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = span.fOther; 500dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndIndex = span.fOtherIndex; 501dac1d17027dcaa5596885a9f333979418b35001ccaryclark oStartIndex = other->nextExactSpan(oEndIndex, -1); 502dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oStartIndex >= 0 && other->span(oStartIndex).fWindValue) { 5034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 5044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 505dac1d17027dcaa5596885a9f333979418b35001ccaryclark oStartIndex = oEndIndex; 506dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndIndex = other->nextExactSpan(oStartIndex, 1); 5074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++spanIndex; 508dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (oEndIndex < 0 || !other->span(oStartIndex).fWindValue); 509dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& oAngle = other->fAngles.push_back(); 510dac1d17027dcaa5596885a9f333979418b35001ccaryclark oAngle.set(other, oEndIndex, oStartIndex); 511dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->setFromAngle(oEndIndex, &oAngle); 5124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *otherPtr = other; 513dac1d17027dcaa5596885a9f333979418b35001ccaryclark return &oAngle; 5144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 516dac1d17027dcaa5596885a9f333979418b35001ccaryclarkSkOpAngle* SkOpSegment::addSingletonAngles(int step) { 5174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other; 518dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle, * otherAngle; 5194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (step > 0) { 520dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherAngle = addSingletonAngleUp(&other, &angle); 5214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 522dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherAngle = addSingletonAngleDown(&other, &angle); 5234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 524dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle->insert(otherAngle); 525dac1d17027dcaa5596885a9f333979418b35001ccaryclark return angle; 5264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 5284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::addStartSpan(int endIndex) { 5294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = 0; 530dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle& angle = fAngles.push_back(); 531dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle.set(this, index, endIndex); 5324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 5334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugCheckPointsEqualish(index, endIndex); 5344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 535dac1d17027dcaa5596885a9f333979418b35001ccaryclark setToAngle(endIndex, &angle); 5364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 538dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::setToAngle(int endIndex, SkOpAngle* angle) { 5394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = 0; 5404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 541dac1d17027dcaa5596885a9f333979418b35001ccaryclark fTs[index].fToAngle = angle; 5424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++index < endIndex); 5434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 5444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 54507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // Defer all coincident edge processing until 54607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // after normal intersections have been computed 54707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 54807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// no need to be tricky; insert in normal T order 54907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// resolve overlapping ts when considering coincidence later 55007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 55107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // add non-coincident intersection. Resulting edges are sorted in T. 552866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.orgint SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { 5534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(this != other || fVerb == SkPath::kCubic_Verb); 5544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org #if 0 // this needs an even rougher association to be useful 5554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt)); 5564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org #endif 557dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& firstPt = fPts[0]; 558dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)]; 559dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(newT == 0 || !precisely_zero(newT)); 560dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(newT == 1 || !precisely_equal(newT, 1)); 56107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: in the pathological case where there is a ton of intercepts, 56207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // binary search? 56307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int insertedAt = -1; 5644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int tCount = fTs.count(); 5654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < tCount; ++index) { 56607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZATION: if there are three or more identical Ts, then 56707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // the fourth and following could be further insertion-sorted so 56807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // that all the edges are clockwise or counterclockwise. 56907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // This could later limit segment tests to the two adjacent 57007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // neighbors, although it doesn't help with determining which 57107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // circular direction to go in. 5727eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com const SkOpSpan& span = fTs[index]; 5737eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (newT < span.fT) { 57407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com insertedAt = index; 57507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 57607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 5777eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (newT == span.fT) { 5787eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (pt == span.fPt) { 5797eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com insertedAt = index; 5807eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com break; 5817eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 5827eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if ((pt == firstPt && newT == 0) || (span.fPt == lastPt && newT == 1)) { 5837eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com insertedAt = index; 5847eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com break; 5857eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 5867eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 58707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 58807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* span; 58907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (insertedAt >= 0) { 59007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span = fTs.insert(insertedAt); 59107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 59207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com insertedAt = tCount; 59307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span = fTs.append(); 59407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 59507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fT = newT; 596dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fOtherT = -1; 59707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOther = other; 59807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fPt = pt; 599a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#if 0 600a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com // cubics, for instance, may not be exact enough to satisfy this check (e.g., cubicOp69d) 601a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) 602a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com && approximately_equal(xyAtT(newT).fY, pt.fY)); 603a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#endif 604dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fFromAngle = NULL; 605dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fToAngle = NULL; 60607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fWindSum = SK_MinS32; 60707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOppSum = SK_MinS32; 60807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fWindValue = 1; 60907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOppValue = 0; 6104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fChased = false; 611dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fCoincident = false; 6124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fLoop = false; 613dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fNear = false; 614dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fMultiple = false; 6154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fSmall = false; 6164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fTiny = false; 617dac1d17027dcaa5596885a9f333979418b35001ccaryclark if ((span->fDone = newT == 1)) { 618dac1d17027dcaa5596885a9f333979418b35001ccaryclark ++fDoneSpans; 619dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 62007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int less = -1; 621dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME: note that this relies on spans being a continguous array 6224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// find range of spans with nearly the same point as this one 62365b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the moment 6244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) { 62507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kCubic_Verb) { 6264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double tInterval = newT - span[less].fT; 62707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double tMid = newT - tInterval / 2; 62807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 62907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!midPt.approximatelyEqual(xyAtT(span))) { 63007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 63107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 63207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 63307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com --less; 63407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 63507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int more = 1; 63665b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the moment 6374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, pt)) { 63807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kCubic_Verb) { 6394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double tEndInterval = span[more].fT - newT; 64007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double tMid = newT - tEndInterval / 2; 64107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid); 64207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!midEndPt.approximatelyEqual(xyAtT(span))) { 64307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 64407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 64507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 64607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++more; 64707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 6484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++less; 6494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --more; 6504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (more - 1 > less && span[more].fPt == span[more - 1].fPt 6514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org && span[more].fT == span[more - 1].fT) { 6524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --more; 6534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (less == more) { 6554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return insertedAt; 6564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (precisely_negative(span[more].fT - span[less].fT)) { 6584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return insertedAt; 6594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// if the total range of t values is big enough, mark all tiny 6614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool tiny = span[less].fPt == span[more].fPt; 6624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = less; 6634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 6644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org fSmall = span[index].fSmall = true; 6654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org fTiny |= span[index].fTiny = tiny; 6664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!span[index].fDone) { 6674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span[index].fDone = true; 6684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++fDoneSpans; 6694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 6704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++index < more); 67107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return insertedAt; 67207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 67307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 67407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// set spans from start to end to decrement by one 67507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// note this walks other backwards 676a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com// FIXME: there's probably an edge case that can be constructed where 67707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// two span in one segment are separated by float epsilon on one span but 67807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// not the other, if one segment is very small. For this 67907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// case the counts asserted below may or may not be enough to separate the 68007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// spans. Even if the counts work out, what if the spans aren't correctly 68107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// sorted? It feels better in such a case to match the span's other span 68207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// pointer since both coincident segments must contain the same spans. 683a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com// FIXME? It seems that decrementing by one will fail for complex paths that 684a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com// have three or more coincident edges. Shouldn't this subtract the difference 685a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com// between the winding values? 686570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com/* |--> |--> 687570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comthis 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>>4 0>>>>1>>>>2>>>>3>>>4 688570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comother 2<<<<1<<<<0 2<<<<1<<<<0 2<<<<1<<<<0 689570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ^ ^ <--| <--| 690570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com startPt endPt test/oTest first pos test/oTest final pos 691570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com*/ 692570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other) { 69307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool binary = fOperand != other->fOperand; 69407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int index = 0; 695570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (startPt != fTs[index].fPt) { 696570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(index < fTs.count()); 69707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++index; 69807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 6994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) { 7007eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com --index; 7017eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 702dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool oFoundEnd = false; 70307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oIndex = other->fTs.count(); 704570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match 705570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(oIndex > 0); 706570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 7077eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double oStartT = other->fTs[oIndex].fT; 7087eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com // look for first point beyond match 7094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other->fTs[oIndex].fT)) { 71065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (!oIndex) { 71165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return; // tiny spans may move in the wrong direction 71265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 713570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 71407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* test = &fTs[index]; 71507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* oTest = &other->fTs[oIndex]; 716570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 717570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 718dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool decrement, track, bigger; 719dac1d17027dcaa5596885a9f333979418b35001ccaryclark int originalWindValue; 720dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint* testPt; 721dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint* oTestPt; 72207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 723570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(test->fT < 1); 724570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(oTest->fT < 1); 725dac1d17027dcaa5596885a9f333979418b35001ccaryclark decrement = test->fWindValue && oTest->fWindValue; 726dac1d17027dcaa5596885a9f333979418b35001ccaryclark track = test->fWindValue || oTest->fWindValue; 727dac1d17027dcaa5596885a9f333979418b35001ccaryclark bigger = test->fWindValue >= oTest->fWindValue; 728dac1d17027dcaa5596885a9f333979418b35001ccaryclark testPt = &test->fPt; 7297eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double testT = test->fT; 730dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTestPt = &oTest->fPt; 7317eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double oTestT = oTest->fT; 73207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 73307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (decrement) { 734a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com if (binary && bigger) { 735570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com test->fOppValue--; 736a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } else { 737570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com decrementSpan(test); 738a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 739570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else if (track) { 740dac1d17027dcaa5596885a9f333979418b35001ccaryclark TrackOutsidePair(&outsidePts, *testPt, *oTestPt); 74107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 742570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(index < fTs.count() - 1); 743570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com test = &fTs[++index]; 744dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (*testPt == test->fPt || precisely_equal(testT, test->fT)); 745dac1d17027dcaa5596885a9f333979418b35001ccaryclark originalWindValue = oTest->fWindValue; 746570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 747570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(oTest->fT < 1); 748570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(originalWindValue == oTest->fWindValue); 74907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (decrement) { 750a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com if (binary && !bigger) { 751570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com oTest->fOppValue--; 752a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } else { 753570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com other->decrementSpan(oTest); 754a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 755570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else if (track) { 756dac1d17027dcaa5596885a9f333979418b35001ccaryclark TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt); 75707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 75807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!oIndex) { 75907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 76007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 761dac1d17027dcaa5596885a9f333979418b35001ccaryclark oFoundEnd |= endPt == oTest->fPt; 762570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com oTest = &other->fTs[--oIndex]; 763dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (*oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT)); 7647eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } while (endPt != test->fPt && test->fT < 1); 76507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: determine if canceled edges need outside ts added 766dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!oFoundEnd) { 767dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int oIdx2 = oIndex; oIdx2 >= 0; --oIdx2) { 768dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* oTst2 = &other->fTs[oIdx2]; 769dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (originalWindValue != oTst2->fWindValue) { 770dac1d17027dcaa5596885a9f333979418b35001ccaryclark goto skipAdvanceOtherCancel; 771dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 772dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!oTst2->fWindValue) { 773dac1d17027dcaa5596885a9f333979418b35001ccaryclark goto skipAdvanceOtherCancel; 774dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 775dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (endPt == other->fTs[oIdx2].fPt) { 776dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 777dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 778dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 779dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 780dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(originalWindValue == oTest->fWindValue); 781dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (decrement) { 782dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (binary && !bigger) { 783dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTest->fOppValue--; 784dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 785dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->decrementSpan(oTest); 786dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 787dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else if (track) { 788dac1d17027dcaa5596885a9f333979418b35001ccaryclark TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt); 789dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 790dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!oIndex) { 791dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 792dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 793dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTest = &other->fTs[--oIndex]; 794dac1d17027dcaa5596885a9f333979418b35001ccaryclark oFoundEnd |= endPt == oTest->fPt; 795dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (!oFoundEnd || endPt == oTest->fPt); 796dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 797dac1d17027dcaa5596885a9f333979418b35001ccaryclarkskipAdvanceOtherCancel: 798570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int outCount = outsidePts.count(); 799570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!done() && outCount) { 800570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com addCancelOutsides(outsidePts[0], outsidePts[1], other); 801570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (outCount > 2) { 802570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com addCancelOutsides(outsidePts[outCount - 2], outsidePts[outCount - 1], other); 80307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 80407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 805570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!other->done() && oOutsidePts.count()) { 806570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this); 80707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 808dac1d17027dcaa5596885a9f333979418b35001ccaryclark setCoincidentRange(startPt, endPt, other); 809dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->setCoincidentRange(startPt, endPt, this); 81007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 81107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 8124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::addSelfT(const SkPoint& pt, double newT) { 813570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // if the tail nearly intersects itself but not quite, the caller records this separately 8144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int result = addT(this, pt, newT); 81507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* span = &fTs[result]; 8164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org fLoop = span->fLoop = true; 81707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return result; 81807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 81907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 820dac1d17027dcaa5596885a9f333979418b35001ccaryclark// find the starting or ending span with an existing loop of angles 821dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME? replicate for all identical starting/ending spans? 822dac1d17027dcaa5596885a9f333979418b35001ccaryclark// OPTIMIZE? remove the spans pointing to windValue==0 here or earlier? 823dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME? assert that only one other span has a valid windValue or oppValue 8244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::addSimpleAngle(int index) { 825dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* span = &fTs[index]; 82619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark int idx; 82719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark int start, end; 82819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (span->fT == 0) { 82919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark idx = 0; 83019eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark span = &fTs[0]; 831dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 832dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span->fToAngle) { 833dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fToAngle->loopCount() == 2); 834dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!span->fFromAngle); 835dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fFromAngle = span->fToAngle->next(); 836dac1d17027dcaa5596885a9f333979418b35001ccaryclark return; 837dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 83819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark span = &fTs[++idx]; 839dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (span->fT == 0); 84019eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(!fTs[0].fTiny && fTs[idx].fT > 0); 84119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark addStartSpan(idx); 84219eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark start = 0; 84319eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark end = idx; 8444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 84519eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark idx = count() - 1; 84619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark span = &fTs[idx]; 847dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 848dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span->fFromAngle) { 849dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fFromAngle->loopCount() == 2); 850dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!span->fToAngle); 851dac1d17027dcaa5596885a9f333979418b35001ccaryclark span->fToAngle = span->fFromAngle->next(); 852dac1d17027dcaa5596885a9f333979418b35001ccaryclark return; 853dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 85419eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark span = &fTs[--idx]; 855dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (span->fT == 1); 85619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(!fTs[idx].fTiny && fTs[idx].fT < 1); 85719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark addEndSpan(++idx); 85819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark start = idx; 85919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark end = count(); 8604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 86119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkOpSegment* other; 86219eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkOpSpan* oSpan; 86319eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark index = start; 86419eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark do { 86519eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark span = &fTs[index]; 86619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark other = span->fOther; 86719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark int oFrom = span->fOtherIndex; 86819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark oSpan = &other->fTs[oFrom]; 86919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (oSpan->fT < 1 && oSpan->fWindValue) { 87019eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark break; 87119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } 87219eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (oSpan->fT == 0) { 87319eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark continue; 87419eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } 87519eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark oFrom = other->nextExactSpan(oFrom, -1); 87619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkOpSpan* oFromSpan = &other->fTs[oFrom]; 87719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(oFromSpan->fT < 1); 87819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (oFromSpan->fWindValue) { 87919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark break; 88019eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } 88119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } while (++index < end); 8824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* angle, * oAngle; 88319eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (span->fT == 0) { 884dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fOtherIndex - 1 >= 0); 885dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fOtherT == 1); 88619eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkDEBUGCODE(int oPriorIndex = other->nextExactSpan(span->fOtherIndex, -1)); 88719eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkDEBUGCODE(const SkOpSpan& oPrior = other->span(oPriorIndex)); 8884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!oPrior.fTiny && oPrior.fT < 1); 889dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->addEndSpan(span->fOtherIndex); 890dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = span->fToAngle; 89119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark oAngle = oSpan->fFromAngle; 8924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 893dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fOtherIndex + 1 < other->count()); 894dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(span->fOtherT == 0); 89519eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark SkASSERT(!oSpan->fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0 896dac1d17027dcaa5596885a9f333979418b35001ccaryclark || (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL 897dac1d17027dcaa5596885a9f333979418b35001ccaryclark && other->fTs[span->fOtherIndex + 1].fToAngle == NULL))); 8984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oIndex = 1; 8994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 9004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& osSpan = other->span(oIndex); 901dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (osSpan.fFromAngle || osSpan.fT > 0) { 9024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 9034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 9044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++oIndex; 9054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(oIndex < other->count()); 9064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (true); 9074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->addStartSpan(oIndex); 908dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = span->fFromAngle; 90919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark oAngle = oSpan->fToAngle; 9104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 9114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->insert(oAngle); 9124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 9134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 914dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::alignMultiples(SkTDArray<AlignedSpan>* alignedArray) { 915dac1d17027dcaa5596885a9f333979418b35001ccaryclark debugValidate(); 916dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 917dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 918dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span = fTs[index]; 919dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!span.fMultiple) { 920dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 921dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 922dac1d17027dcaa5596885a9f333979418b35001ccaryclark int end = nextExactSpan(index, 1); 923dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(end > index + 1); 924dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& thisPt = span.fPt; 925dac1d17027dcaa5596885a9f333979418b35001ccaryclark while (index < end - 1) { 926dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other1 = span.fOther; 927dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oCnt = other1->count(); 928dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int idx2 = index + 1; idx2 < end; ++idx2) { 929dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span2 = fTs[idx2]; 930dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other2 = span2.fOther; 931dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int oIdx = 0; oIdx < oCnt; ++oIdx) { 932dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan = other1->fTs[oIdx]; 933dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oSpan.fOther != other2) { 934dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 935dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 936dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oSpan.fPt == thisPt) { 937dac1d17027dcaa5596885a9f333979418b35001ccaryclark goto skipExactMatches; 938dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 939dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 940dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int oIdx = 0; oIdx < oCnt; ++oIdx) { 941dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan = other1->fTs[oIdx]; 942dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oSpan.fOther != other2) { 943dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 944dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 945dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (SkDPoint::RoughlyEqual(oSpan.fPt, thisPt)) { 946dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan2 = other2->fTs[oSpan.fOtherIndex]; 947dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (zero_or_one(span.fOtherT) || zero_or_one(oSpan.fT) 948dac1d17027dcaa5596885a9f333979418b35001ccaryclark || zero_or_one(span2.fOtherT) || zero_or_one(oSpan2.fT)) { 949dac1d17027dcaa5596885a9f333979418b35001ccaryclark return; 950dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 951dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!way_roughly_equal(span.fOtherT, oSpan.fT) 952dac1d17027dcaa5596885a9f333979418b35001ccaryclark || !way_roughly_equal(span2.fOtherT, oSpan2.fT) 953dac1d17027dcaa5596885a9f333979418b35001ccaryclark || !way_roughly_equal(span2.fOtherT, oSpan.fOtherT) 954dac1d17027dcaa5596885a9f333979418b35001ccaryclark || !way_roughly_equal(span.fOtherT, oSpan2.fOtherT)) { 955dac1d17027dcaa5596885a9f333979418b35001ccaryclark return; 956dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 957dac1d17027dcaa5596885a9f333979418b35001ccaryclark alignSpan(thisPt, span.fOtherT, other1, span2.fOtherT, 958dac1d17027dcaa5596885a9f333979418b35001ccaryclark other2, &oSpan, alignedArray); 959dac1d17027dcaa5596885a9f333979418b35001ccaryclark alignSpan(thisPt, span2.fOtherT, other2, span.fOtherT, 960dac1d17027dcaa5596885a9f333979418b35001ccaryclark other1, &oSpan2, alignedArray); 961dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 962dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 963dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 964dac1d17027dcaa5596885a9f333979418b35001ccaryclark skipExactMatches: 965dac1d17027dcaa5596885a9f333979418b35001ccaryclark ; 966dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 967dac1d17027dcaa5596885a9f333979418b35001ccaryclark ++index; 968dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 969dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 970dac1d17027dcaa5596885a9f333979418b35001ccaryclark debugValidate(); 971dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 972dac1d17027dcaa5596885a9f333979418b35001ccaryclark 973dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, 974dac1d17027dcaa5596885a9f333979418b35001ccaryclark double otherT, const SkOpSegment* other2, SkOpSpan* oSpan, 975dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkTDArray<AlignedSpan>* alignedArray) { 976dac1d17027dcaa5596885a9f333979418b35001ccaryclark AlignedSpan* aligned = alignedArray->append(); 977dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fOldPt = oSpan->fPt; 978dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fPt = newPt; 979dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fOldT = oSpan->fT; 980dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fT = newT; 981dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fSegment = this; // OPTIMIZE: may be unused, can remove 982dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fOther1 = other; 983dac1d17027dcaa5596885a9f333979418b35001ccaryclark aligned->fOther2 = other2; 984dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(SkDPoint::RoughlyEqual(oSpan->fPt, newPt)); 985dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan->fPt = newPt; 986dac1d17027dcaa5596885a9f333979418b35001ccaryclark// SkASSERT(way_roughly_equal(oSpan->fT, newT)); 987dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan->fT = newT; 988dac1d17027dcaa5596885a9f333979418b35001ccaryclark// SkASSERT(way_roughly_equal(oSpan->fOtherT, otherT)); 989dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan->fOtherT = otherT; 990dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 991dac1d17027dcaa5596885a9f333979418b35001ccaryclark 9924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgbool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) { 9934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool aligned = false; 9944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* span = &fTs[index]; 9954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = span->fOther; 9964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oIndex = span->fOtherIndex; 9974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* oSpan = &other->fTs[oIndex]; 9984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span->fT != thisT) { 9994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fT = thisT; 10004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oSpan->fOtherT = thisT; 10014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org aligned = true; 10024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span->fPt != thisPt) { 10044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fPt = thisPt; 10054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oSpan->fPt = thisPt; 10064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org aligned = true; 10074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double oT = oSpan->fT; 10098cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (oT == 0) { 10104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return aligned; 10114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oStart = other->nextSpan(oIndex, -1) + 1; 10134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oSpan = &other->fTs[oStart]; 10148cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int otherIndex = oStart; 10158cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (oT == 1) { 10168cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (aligned) { 10178cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org while (oSpan->fPt == thisPt && oSpan->fT != 1) { 10188cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org oSpan->fTiny = true; 10198cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org ++oSpan; 10208cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 10218cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 10228cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return aligned; 10238cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 10244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oT = oSpan->fT; 10258cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int oEnd = other->nextSpan(oIndex, 1); 10264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool oAligned = false; 10274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oSpan->fPt != thisPt) { 10284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oAligned |= other->alignSpan(oStart, oT, thisPt); 10294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++otherIndex < oEnd) { 10314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* oNextSpan = &other->fTs[otherIndex]; 10324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oNextSpan->fT != oT || oNextSpan->fPt != thisPt) { 10334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oAligned |= other->alignSpan(otherIndex, oT, thisPt); 10344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oAligned) { 10374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->alignSpanState(oStart, oEnd); 10384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return aligned; 10404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 10424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::alignSpanState(int start, int end) { 10434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* lastSpan = &fTs[--end]; 10444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool allSmall = lastSpan->fSmall; 10454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool allTiny = lastSpan->fTiny; 10464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool allDone = lastSpan->fDone; 10474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDEBUGCODE(int winding = lastSpan->fWindValue); 10484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDEBUGCODE(int oppWinding = lastSpan->fOppValue); 10494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = start; 10504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (index < end) { 10514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* span = &fTs[index]; 10524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fSmall = allSmall; 10534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fTiny = allTiny; 10544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span->fDone != allDone) { 10554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span->fDone = allDone; 10564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org fDoneSpans += allDone ? 1 : -1; 10574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(span->fWindValue == winding); 10594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(span->fOppValue == oppWinding); 10604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++index; 10614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 10624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 10634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1064dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::blindCancel(const SkCoincidence& coincidence, SkOpSegment* other) { 1065dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool binary = fOperand != other->fOperand; 1066dac1d17027dcaa5596885a9f333979418b35001ccaryclark int index = 0; 1067dac1d17027dcaa5596885a9f333979418b35001ccaryclark int last = this->count(); 1068dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1069dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span = this->fTs[--last]; 1070dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fT != 1 && !span.fSmall) { 1071dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1072dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1073dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fCoincident = true; 1074dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (true); 1075dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oIndex = other->count(); 1076dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1077dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan = other->fTs[--oIndex]; 1078dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oSpan.fT != 1 && !oSpan.fSmall) { 1079dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1080dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1081dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan.fCoincident = true; 1082dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (true); 1083dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1084dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* test = &this->fTs[index]; 1085dac1d17027dcaa5596885a9f333979418b35001ccaryclark int baseWind = test->fWindValue; 1086dac1d17027dcaa5596885a9f333979418b35001ccaryclark int baseOpp = test->fOppValue; 1087dac1d17027dcaa5596885a9f333979418b35001ccaryclark int endIndex = index; 1088dac1d17027dcaa5596885a9f333979418b35001ccaryclark while (++endIndex <= last) { 1089dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* endSpan = &this->fTs[endIndex]; 1090dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(endSpan->fT < 1); 1091dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp) { 1092dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1093dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1094dac1d17027dcaa5596885a9f333979418b35001ccaryclark endSpan->fCoincident = true; 1095dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1096dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* oTest = &other->fTs[oIndex]; 1097dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oBaseWind = oTest->fWindValue; 1098dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oBaseOpp = oTest->fOppValue; 1099dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oStartIndex = oIndex; 1100dac1d17027dcaa5596885a9f333979418b35001ccaryclark while (--oStartIndex >= 0) { 1101dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* oStartSpan = &other->fTs[oStartIndex]; 1102dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oStartSpan->fWindValue != oBaseWind || oStartSpan->fOppValue != oBaseOpp) { 1103dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1104dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1105dac1d17027dcaa5596885a9f333979418b35001ccaryclark oStartSpan->fCoincident = true; 1106dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1107dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool decrement = baseWind && oBaseWind; 1108dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool bigger = baseWind >= oBaseWind; 1109dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1110dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(test->fT < 1); 1111dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (decrement) { 1112dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (binary && bigger) { 1113dac1d17027dcaa5596885a9f333979418b35001ccaryclark test->fOppValue--; 1114dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1115dac1d17027dcaa5596885a9f333979418b35001ccaryclark decrementSpan(test); 1116dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1117dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1118dac1d17027dcaa5596885a9f333979418b35001ccaryclark test->fCoincident = true; 1119dac1d17027dcaa5596885a9f333979418b35001ccaryclark test = &fTs[++index]; 1120dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (index < endIndex); 1121dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1122dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(oTest->fT < 1); 1123dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (decrement) { 1124dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (binary && !bigger) { 1125dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTest->fOppValue--; 1126dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1127dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->decrementSpan(oTest); 1128dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1129dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1130dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTest->fCoincident = true; 1131dac1d17027dcaa5596885a9f333979418b35001ccaryclark oTest = &other->fTs[--oIndex]; 1132dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (oIndex > oStartIndex); 1133dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (index <= last && oIndex >= 0); 1134dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(index > last); 1135dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(oIndex < 0); 1136dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1137dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1138dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other) { 1139dac1d17027dcaa5596885a9f333979418b35001ccaryclark bool binary = fOperand != other->fOperand; 1140dac1d17027dcaa5596885a9f333979418b35001ccaryclark int index = 0; 1141dac1d17027dcaa5596885a9f333979418b35001ccaryclark int last = this->count(); 1142dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1143dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span = this->fTs[--last]; 1144dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fT != 1 && !span.fSmall) { 1145dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1146dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1147dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fCoincident = true; 1148dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (true); 1149dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oIndex = 0; 1150dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oLast = other->count(); 1151dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1152dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan = other->fTs[--oLast]; 1153dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oSpan.fT != 1 && !oSpan.fSmall) { 1154dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1155dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1156dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan.fCoincident = true; 1157dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (true); 1158dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1159dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* test = &this->fTs[index]; 1160dac1d17027dcaa5596885a9f333979418b35001ccaryclark int baseWind = test->fWindValue; 1161dac1d17027dcaa5596885a9f333979418b35001ccaryclark int baseOpp = test->fOppValue; 1162dac1d17027dcaa5596885a9f333979418b35001ccaryclark int endIndex = index; 1163dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* endSpan; 1164dac1d17027dcaa5596885a9f333979418b35001ccaryclark while (++endIndex <= last) { 1165dac1d17027dcaa5596885a9f333979418b35001ccaryclark endSpan = &this->fTs[endIndex]; 1166dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(endSpan->fT < 1); 1167dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp) { 1168dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1169dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1170dac1d17027dcaa5596885a9f333979418b35001ccaryclark endSpan->fCoincident = true; 1171dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1172dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* oTest = &other->fTs[oIndex]; 1173dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oBaseWind = oTest->fWindValue; 1174dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oBaseOpp = oTest->fOppValue; 1175dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oEndIndex = oIndex; 1176dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* oEndSpan; 1177dac1d17027dcaa5596885a9f333979418b35001ccaryclark while (++oEndIndex <= oLast) { 1178dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndSpan = &this->fTs[oEndIndex]; 1179dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(oEndSpan->fT < 1); 1180dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oEndSpan->fWindValue != oBaseWind || oEndSpan->fOppValue != oBaseOpp) { 1181dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 1182dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1183dac1d17027dcaa5596885a9f333979418b35001ccaryclark oEndSpan->fCoincident = true; 1184dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1185dac1d17027dcaa5596885a9f333979418b35001ccaryclark // consolidate the winding count even if done 1186dac1d17027dcaa5596885a9f333979418b35001ccaryclark if ((test->fWindValue || test->fOppValue) && (oTest->fWindValue || oTest->fOppValue)) { 1187dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 1188dac1d17027dcaa5596885a9f333979418b35001ccaryclark bumpCoincidentBlind(binary, index, endIndex); 1189dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->bumpCoincidentOBlind(oIndex, oEndIndex); 1190dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1191dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->bumpCoincidentBlind(binary, oIndex, oEndIndex); 1192dac1d17027dcaa5596885a9f333979418b35001ccaryclark bumpCoincidentOBlind(index, endIndex); 1193dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1194dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1195dac1d17027dcaa5596885a9f333979418b35001ccaryclark index = endIndex; 1196dac1d17027dcaa5596885a9f333979418b35001ccaryclark oIndex = oEndIndex; 1197dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (index <= last && oIndex <= oLast); 1198dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(index > last); 1199dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(oIndex > oLast); 1200dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1201dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1202dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::bumpCoincidentBlind(bool binary, int index, int endIndex) { 1203dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& oTest = fTs[index]; 1204dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oWindValue = oTest.fWindValue; 1205dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oOppValue = oTest.fOppValue; 1206dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (binary) { 1207dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkTSwap<int>(oWindValue, oOppValue); 1208dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1209dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1210dac1d17027dcaa5596885a9f333979418b35001ccaryclark (void) bumpSpan(&fTs[index], oWindValue, oOppValue); 1211dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (++index < endIndex); 1212dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1213dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1214570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* indexPtr, 1215570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkTArray<SkPoint, true>* outsideTs) { 1216570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int index = *indexPtr; 121707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oWindValue = oTest.fWindValue; 121807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oOppValue = oTest.fOppValue; 1219570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 122007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(oWindValue, oOppValue); 122107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 122207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* const test = &fTs[index]; 122307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* end = test; 1224570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint& oStartPt = oTest.fPt; 122507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 122607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (bumpSpan(end, oWindValue, oOppValue)) { 1227570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com TrackOutside(outsideTs, oStartPt); 122807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 122907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com end = &fTs[++index]; 12304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && end->fT < 1); 1231570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com *indexPtr = index; 1232570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1233570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1234dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) { 1235dac1d17027dcaa5596885a9f333979418b35001ccaryclark do { 1236dac1d17027dcaa5596885a9f333979418b35001ccaryclark zeroSpan(&fTs[index]); 1237dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (++index < endIndex); 1238dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1239dac1d17027dcaa5596885a9f333979418b35001ccaryclark 124007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// because of the order in which coincidences are resolved, this and other 124107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// may not have the same intermediate points. Compute the corresponding 124207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// intermediate T values (using this as the master, other as the follower) 124307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// and walk other conditionally -- hoping that it catches up in the end 1244570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, 1245570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkTArray<SkPoint, true>* oOutsidePts) { 1246570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int oIndex = *oIndexPtr; 124707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* const oTest = &fTs[oIndex]; 124807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* oEnd = oTest; 1249570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint& oStartPt = oTest->fPt; 12507eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double oStartT = oTest->fT; 12514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if 0 // FIXME : figure out what disabling this breaks 12524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& startPt = test.fPt; 12534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // this is always true since oEnd == oTest && oStartPt == oTest->fPt -- find proper condition 12544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) { 1255570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com TrackOutside(oOutsidePts, startPt); 1256570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 12574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 12584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) { 125907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com zeroSpan(oEnd); 126007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oEnd = &fTs[++oIndex]; 126107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1262570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com *oIndexPtr = oIndex; 126307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 126407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 126507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// FIXME: need to test this case: 126607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// contourA has two segments that are coincident 126707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// contourB has two segments that are coincident in the same place 126807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// each ends up with +2/0 pairs for winding count 126907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// since logic below doesn't transfer count (only increments/decrements) can this be 127007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// resolved to +4/0 ? 127107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 127207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// set spans from start to end to increment the greater by one and decrement 127307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// the lesser 1274630240d18805faf81d8e75172496ad165c2226b2caryclarkbool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT, 1275570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* other) { 1276570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool binary = fOperand != other->fOperand; 127707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int index = 0; 1278570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (startPt != fTs[index].fPt) { 1279570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(index < fTs.count()); 128007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++index; 128107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 12827eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double startT = fTs[index].fT; 12834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (index > 0 && precisely_equal(fTs[index - 1].fT, startT)) { 12847eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com --index; 12857eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 128607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oIndex = 0; 1287570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (startPt != other->fTs[oIndex].fPt) { 1288570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(oIndex < other->fTs.count()); 128907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++oIndex; 129007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 12917eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double oStartT = other->fTs[oIndex].fT; 12924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (oIndex > 0 && precisely_equal(other->fTs[oIndex - 1].fT, oStartT)) { 12937eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com --oIndex; 12947eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 1295570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts; 1296570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts; 129707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* test = &fTs[index]; 1298570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint* testPt = &test->fPt; 12997eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com double testT = test->fT; 130007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* oTest = &other->fTs[oIndex]; 1301570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint* oTestPt = &oTest->fPt; 1302361b8b088589748e4b29895a4ebc5316e881e219caryclark // paths with extreme data will fail this test and eject out of pathops altogether later on 1303361b8b088589748e4b29895a4ebc5316e881e219caryclark // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 130407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 1305570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(test->fT < 1); 1306630240d18805faf81d8e75172496ad165c2226b2caryclark if (oTest->fT == 1) { 1307630240d18805faf81d8e75172496ad165c2226b2caryclark // paths with extreme data may be so mismatched that we fail here 1308630240d18805faf81d8e75172496ad165c2226b2caryclark return false; 1309630240d18805faf81d8e75172496ad165c2226b2caryclark } 13104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 13114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // consolidate the winding count even if done 1312570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if ((test->fWindValue == 0 && test->fOppValue == 0) 1313570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) { 1314570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDEBUGCODE(int firstWind = test->fWindValue); 1315570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDEBUGCODE(int firstOpp = test->fOppValue); 1316570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 1317570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(firstWind == fTs[index].fWindValue); 1318570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(firstOpp == fTs[index].fOppValue); 1319570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ++index; 1320570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(index < fTs.count()); 1321570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (*testPt == fTs[index].fPt); 1322570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDEBUGCODE(firstWind = oTest->fWindValue); 1323570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDEBUGCODE(firstOpp = oTest->fOppValue); 1324570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 1325570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(firstWind == other->fTs[oIndex].fWindValue); 1326570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(firstOpp == other->fTs[oIndex].fOppValue); 1327570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ++oIndex; 1328570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(oIndex < other->fTs.count()); 1329570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (*oTestPt == other->fTs[oIndex].fPt); 133007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 1331570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 1332570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bumpCoincidentThis(*oTest, binary, &index, &outsidePts); 1333570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 1334570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else { 1335570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts); 1336570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bumpCoincidentOther(*oTest, &index, &outsidePts); 1337570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 133807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 133907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com test = &fTs[index]; 1340570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com testPt = &test->fPt; 13417eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com testT = test->fT; 134207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oTest = &other->fTs[oIndex]; 1343570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com oTestPt = &oTest->fPt; 13444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (endPt == *testPt || precisely_equal(endT, testT)) { 13454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 13464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 13474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); 1348570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (endPt != *oTestPt); 13494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // in rare cases, one may have ended before the other 13504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (endPt != *testPt && !precisely_equal(endT, testT)) { 13517eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com int lastWind = test[-1].fWindValue; 13527eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com int lastOpp = test[-1].fOppValue; 13537eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com bool zero = lastWind == 0 && lastOpp == 0; 13547eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com do { 13557eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (test->fWindValue || test->fOppValue) { 13567eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com test->fWindValue = lastWind; 13577eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com test->fOppValue = lastOpp; 13587eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (zero) { 13597eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com test->fDone = true; 13607eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com ++fDoneSpans; 13617eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 13627eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 13637eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com test = &fTs[++index]; 13647eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com testPt = &test->fPt; 13657eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } while (endPt != *testPt); 13664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 13674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (endPt != *oTestPt) { 13684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // look ahead to see if zeroing more spans will allows us to catch up 13694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oPeekIndex = oIndex; 13704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool success = true; 13714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan* oPeek; 1372dac1d17027dcaa5596885a9f333979418b35001ccaryclark int oCount = other->count(); 13734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 13744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oPeek = &other->fTs[oPeekIndex]; 1375dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (++oPeekIndex == oCount) { 13764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org success = false; 13774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 13784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 13794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (endPt != oPeek->fPt); 13804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (success) { 13814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // make sure the matching point completes the coincidence span 13824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org success = false; 13834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 13844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oPeek->fOther == this) { 13854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org success = true; 13864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 13874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 138819eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark if (++oPeekIndex == oCount) { 138919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark break; 139019eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark } 139119eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark oPeek = &other->fTs[oPeekIndex]; 13924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (endPt == oPeek->fPt); 13934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 13944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (success) { 13954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 13964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!binary || test->fWindValue + oTest->fOppValue >= 0) { 13974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); 13984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 13994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts); 14004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 14014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oTest = &other->fTs[oIndex]; 14024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oTestPt = &oTest->fPt; 14034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (endPt != *oTestPt); 14044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 14054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1406570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int outCount = outsidePts.count(); 1407570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!done() && outCount) { 1408570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com addCoinOutsides(outsidePts[0], endPt, other); 140907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1410570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!other->done() && oOutsidePts.count()) { 1411570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com other->addCoinOutsides(oOutsidePts[0], endPt, this); 141207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1413dac1d17027dcaa5596885a9f333979418b35001ccaryclark setCoincidentRange(startPt, endPt, other); 1414dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->setCoincidentRange(startPt, endPt, this); 1415630240d18805faf81d8e75172496ad165c2226b2caryclark return true; 141607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 141707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 141807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// FIXME: this doesn't prevent the same span from being added twice 141907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// fix in caller, SkASSERT here? 142065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// FIXME: this may erroneously reject adds for cubic loops 14214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, 1422dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& pt, const SkPoint& pt2) { 142307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int tCount = fTs.count(); 142407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int tIndex = 0; tIndex < tCount; ++tIndex) { 142507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& span = fTs[tIndex]; 142607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!approximately_negative(span.fT - t)) { 142707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 142807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 142965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (span.fOther == other) { 143065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark bool tsMatch = approximately_equal(span.fT, t); 143165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark bool otherTsMatch = approximately_equal(span.fOtherT, otherT); 143265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark // FIXME: add cubic loop detecting logic here 143365b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark // if fLoop bit is set on span, that could be enough if addOtherT copies the bit 143465b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark // or if a new bit is added ala fOtherLoop 143565b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (tsMatch || otherTsMatch) { 143607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ADD_T_PAIR 143765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", 143865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark __FUNCTION__, fID, t, other->fID, otherT); 143907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 144065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 144165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 144265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 144365b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 144465b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark int oCount = other->count(); 144565b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark for (int oIndex = 0; oIndex < oCount; ++oIndex) { 144665b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark const SkOpSpan& oSpan = other->span(oIndex); 144765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (!approximately_negative(oSpan.fT - otherT)) { 144865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark break; 144965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 145065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (oSpan.fOther == this) { 145165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark bool otherTsMatch = approximately_equal(oSpan.fT, otherT); 145265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark bool tsMatch = approximately_equal(oSpan.fOtherT, t); 145365b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (otherTsMatch || tsMatch) { 145465b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark#if DEBUG_ADD_T_PAIR 145565b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkDebugf("%s addTPair other duplicate this=%d %1.9g other=%d %1.9g\n", 145665b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark __FUNCTION__, fID, t, other->fID, otherT); 145765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark#endif 145865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 145965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 146007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 146107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 146207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_ADD_T_PAIR 146307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", 146407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, fID, t, other->fID, otherT); 146507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 146665b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkASSERT(other != this); 1467866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org int insertedAt = addT(other, pt, t); 1468dac1d17027dcaa5596885a9f333979418b35001ccaryclark int otherInsertedAt = other->addT(this, pt2, otherT); 146907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com addOtherT(insertedAt, otherT, otherInsertedAt); 147007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->addOtherT(otherInsertedAt, t, insertedAt); 147107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com matchWindingValue(insertedAt, t, borrowWind); 147207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->matchWindingValue(otherInsertedAt, otherT, borrowWind); 1473dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span = this->fTs[insertedAt]; 1474dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (pt != pt2) { 1475dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fNear = true; 1476dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& oSpan = other->fTs[otherInsertedAt]; 1477dac1d17027dcaa5596885a9f333979418b35001ccaryclark oSpan.fNear = true; 1478dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1479dac1d17027dcaa5596885a9f333979418b35001ccaryclark return &span; 148007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 148107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1482dac1d17027dcaa5596885a9f333979418b35001ccaryclarkconst SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, 1483dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& pt) { 1484dac1d17027dcaa5596885a9f333979418b35001ccaryclark return addTPair(t, other, otherT, borrowWind, pt, pt); 148507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 148607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1487570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { 1488570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint midPt = ptAtT(midT); 1489570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkPathOpsBounds bounds; 1490570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bounds.set(pt1.fX, pt1.fY, pt2.fX, pt2.fY); 1491570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bounds.sort(); 1492570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return bounds.almostContains(midPt); 1493570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1494570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 149507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::betweenTs(int lesser, double testT, int greater) const { 149607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (lesser > greater) { 149707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(lesser, greater); 149807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 149907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT); 150007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 150107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 15024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// in extreme cases (like the buffer overflow test) return false to abort 15034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// for now, if one t value represents two different points, then the values are too extreme 15044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// to generate meaningful results 15054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgbool SkOpSegment::calcAngles() { 15064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int spanCount = fTs.count(); 15074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (spanCount <= 2) { 15084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return spanCount == 2; 15094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = 1; 15114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* firstSpan = &fTs[index]; 15124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int activePrior = checkSetAngle(0); 15134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* span = &fTs[0]; 15144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther->multipleEnds()) { 15154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index = findStartSpan(0); // curve start intersects 1516361b8b088589748e4b29895a4ebc5316e881e219caryclark if (fTs[index].fT == 0) { 1517361b8b088589748e4b29895a4ebc5316e881e219caryclark return false; 1518361b8b088589748e4b29895a4ebc5316e881e219caryclark } 1519dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(index > 0); 15204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (activePrior >= 0) { 15214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addStartSpan(index); 1522570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 15234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool addEnd; 15254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int endIndex = spanCount - 1; 15264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span = &fTs[endIndex - 1]; 15274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects 15284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org endIndex = findEndSpan(endIndex); 1529dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(endIndex > 0); 15304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 15314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleStarts(); 15324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(endIndex >= index); 15344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int prior = 0; 15354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (index < endIndex) { 15364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& fromSpan = fTs[index]; // for each intermediate intersection 15374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* lastSpan; 15384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span = &fromSpan; 15394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int start = index; 15404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 15414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org lastSpan = span; 15424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span = &fTs[++index]; 15434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(index < spanCount); 15444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny) { 1545570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com break; 1546570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 15474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) { 15484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 15494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (true); 1551dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle = NULL; 1552dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* priorAngle; 15534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (activePrior >= 0) { 15544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int pActive = firstActive(prior); 15554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(pActive < start); 1556dac1d17027dcaa5596885a9f333979418b35001ccaryclark priorAngle = &fAngles.push_back(); 1557dac1d17027dcaa5596885a9f333979418b35001ccaryclark priorAngle->set(this, start, pActive); 155807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int active = checkSetAngle(start); 15604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (active >= 0) { 15614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(active < index); 1562dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = &fAngles.push_back(); 1563dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle->set(this, active, index); 156407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org #if DEBUG_ANGLE 15664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugCheckPointsEqualish(start, index); 15674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org #endif 15684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org prior = start; 15694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 15704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* startSpan = &fTs[start - 1]; 1571dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!startSpan->fSmall || isCanceled(start - 1) || startSpan->fFromAngle 1572dac1d17027dcaa5596885a9f333979418b35001ccaryclark || startSpan->fToAngle) { 15734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 15744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --start; 15764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (start > 0); 15774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 15784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (activePrior >= 0) { 1579dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(fTs[start].fFromAngle == NULL); 1580dac1d17027dcaa5596885a9f333979418b35001ccaryclark fTs[start].fFromAngle = priorAngle; 15814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (active >= 0) { 1583dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(fTs[start].fToAngle == NULL); 1584dac1d17027dcaa5596885a9f333979418b35001ccaryclark fTs[start].fToAngle = angle; 15854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 15864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++start < index); 15874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org activePrior = active; 158807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 15894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (addEnd && activePrior >= 0) { 15904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addEndSpan(endIndex); 1591570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 15924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 15934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 15944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 15954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::checkSetAngle(int tIndex) const { 15964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* span = &fTs[tIndex]; 15974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (span->fTiny /* || span->fSmall */) { 15984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span = &fTs[++tIndex]; 1599570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 16004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return isCanceled(tIndex) ? -1 : tIndex; 16014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 16024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1603dac1d17027dcaa5596885a9f333979418b35001ccaryclark// at this point, the span is already ordered, or unorderable 16044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) { 16054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(includeType != SkOpAngle::kUnaryXor); 16064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex); 160765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (NULL == firstAngle || NULL == firstAngle->next()) { 16084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return SK_NaN32; 1609570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1610570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // if all angles have a computed winding, 1611570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if no adjacent angles are orderable, 1612570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // or if adjacent orderable angles have no computed winding, 1613570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // there's nothing to do 1614dac1d17027dcaa5596885a9f333979418b35001ccaryclark // if two orderable angles are adjacent, and both are next to orderable angles, 1615dac1d17027dcaa5596885a9f333979418b35001ccaryclark // and one has winding computed, transfer to the other 16164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* baseAngle = NULL; 1617570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool tryReverse = false; 1618570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // look for counterclockwise transfers 1619dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle = firstAngle->previous(); 1620dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* next = angle->next(); 1621dac1d17027dcaa5596885a9f333979418b35001ccaryclark firstAngle = next; 162207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 1623dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = angle; 1624dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = next; 1625dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 1626dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 1627dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(angle->next() == next); 1628dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 1629dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = NULL; 16304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 16314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1632dac1d17027dcaa5596885a9f333979418b35001ccaryclark int testWinding = angle->segment()->windSum(angle); 1633dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (SK_MinS32 != testWinding) { 1634dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = angle; 16354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 16364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 16374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 16384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (baseAngle) { 16394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSum(baseAngle, angle, includeType); 16404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL; 16414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 1642dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (next != firstAngle); 1643dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(firstAngle)) { 16444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle = baseAngle; 16454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org tryReverse = true; 16464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 16474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (tryReverse) { 16484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = NULL; 1649dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* prior = firstAngle; 1650570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com do { 1651dac1d17027dcaa5596885a9f333979418b35001ccaryclark angle = prior; 1652dac1d17027dcaa5596885a9f333979418b35001ccaryclark prior = angle->previous(); 1653dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(prior->next() == angle); 1654dac1d17027dcaa5596885a9f333979418b35001ccaryclark next = angle->next(); 1655dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (prior->unorderable() || angle->unorderable() || next->unorderable()) { 1656dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = NULL; 1657dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 1658dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 16594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int testWinding = angle->segment()->windSum(angle); 16604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (SK_MinS32 != testWinding) { 16614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = angle; 1662570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 166307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1664570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (baseAngle) { 16654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ComputeOneSumReverse(baseAngle, angle, includeType); 16664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL; 1667570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1668dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (prior != firstAngle); 1669570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 167007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int minIndex = SkMin32(startIndex, endIndex); 167107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return windSum(minIndex); 167207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 167307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1674570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 1675570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpAngle::IncludeType includeType) { 1676570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSegment* baseSegment = baseAngle->segment(); 1677570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 1678570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int sumSuWinding; 1679570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool binary = includeType >= SkOpAngle::kBinarySingle; 1680570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 1681570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); 1682570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (baseSegment->operand()) { 1683570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 1684570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1685570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1686570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* nextSegment = nextAngle->segment(); 1687570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int maxWinding, sumWinding; 1688570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* last; 1689570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 1690570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int oppMaxWinding, oppSumWinding; 1691570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 1692570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 1693570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 1694866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org nextAngle); 1695570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else { 1696570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, 1697570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com &maxWinding, &sumWinding); 1698866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 1699570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1700570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextAngle->setLastMarked(last); 1701570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1702570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 1703570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, 1704570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpAngle::IncludeType includeType) { 1705570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSegment* baseSegment = baseAngle->segment(); 1706570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int sumMiWinding = baseSegment->updateWinding(baseAngle); 1707570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int sumSuWinding; 1708570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool binary = includeType >= SkOpAngle::kBinarySingle; 1709570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 1710570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com sumSuWinding = baseSegment->updateOppWinding(baseAngle); 1711570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (baseSegment->operand()) { 1712570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 1713570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1714570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1715570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* nextSegment = nextAngle->segment(); 1716570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int maxWinding, sumWinding; 1717570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* last; 1718570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (binary) { 1719570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int oppMaxWinding, oppSumWinding; 1720570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 1721570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); 1722570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, 1723866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org nextAngle); 1724570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else { 1725570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, 1726570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com &maxWinding, &sumWinding); 1727866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); 1728570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 1729570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextAngle->setLastMarked(last); 1730570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 1731570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 17328cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.orgbool SkOpSegment::containsPt(const SkPoint& pt, int index, int endIndex) const { 17338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int step = index < endIndex ? 1 : -1; 17348cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org do { 17358cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org const SkOpSpan& span = this->span(index); 17368cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (span.fPt == pt) { 17378cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org const SkOpSpan& endSpan = this->span(endIndex); 17388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return span.fT == endSpan.fT && pt != endSpan.fPt; 17398cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 17408cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org index += step; 17418cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } while (index != endIndex); 17428cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return false; 17434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 17444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1745dac1d17027dcaa5596885a9f333979418b35001ccaryclarkbool SkOpSegment::containsT(double t, const SkOpSegment* other, double otherT) const { 1746dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 1747dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 1748dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = fTs[index]; 1749dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (t < span.fT) { 1750dac1d17027dcaa5596885a9f333979418b35001ccaryclark return false; 1751dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1752dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (t == span.fT) { 1753dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (other != span.fOther) { 1754dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 1755dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1756dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (other->fVerb != SkPath::kCubic_Verb) { 1757dac1d17027dcaa5596885a9f333979418b35001ccaryclark return true; 1758dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1759dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!other->fLoop) { 1760dac1d17027dcaa5596885a9f333979418b35001ccaryclark return true; 1761dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1762dac1d17027dcaa5596885a9f333979418b35001ccaryclark double otherMidT = (otherT + span.fOtherT) / 2; 1763dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkPoint otherPt = other->ptAtT(otherMidT); 1764dac1d17027dcaa5596885a9f333979418b35001ccaryclark return SkDPoint::ApproximatelyEqual(span.fPt, otherPt); 1765dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1766dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1767dac1d17027dcaa5596885a9f333979418b35001ccaryclark return false; 1768dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1769dac1d17027dcaa5596885a9f333979418b35001ccaryclark 177007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, 177107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool* hitSomething, double mid, bool opp, bool current) const { 177207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar bottom = fBounds.fBottom; 177307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int bestTIndex = -1; 177407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (bottom <= *bestY) { 177507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 177607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 177707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar top = fBounds.fTop; 177807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (top >= basePt.fY) { 177907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 178007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 178107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fLeft > basePt.fX) { 178207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 178307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 178407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fRight < basePt.fX) { 178507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 178607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 178707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fBounds.fLeft == fBounds.fRight) { 178807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if vertical, and directly above test point, wait for another one 178907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTIndex; 179007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 179107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // intersect ray starting at basePt with edge 179207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkIntersections intersections; 179307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZE: use specialty function that intersects ray with curve, 179407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // returning t values only for curve (we don't care about t on ray) 1795a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com intersections.allowNear(false); 1796cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int pts = (intersections.*CurveVertical[SkPathOpsVerbToPoints(fVerb)]) 1797cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (fPts, top, bottom, basePt.fX, false); 179807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (pts == 0 || (current && pts == 1)) { 179907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 180007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 180107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (current) { 180207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(pts > 1); 180307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int closestIdx = 0; 180407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double closest = fabs(intersections[0][0] - mid); 180507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int idx = 1; idx < pts; ++idx) { 180607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double test = fabs(intersections[0][idx] - mid); 180707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (closest > test) { 180807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com closestIdx = idx; 180907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com closest = test; 181007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 181107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 181207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com intersections.quickRemoveOne(closestIdx, --pts); 181307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 181407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double bestT = -1; 181507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int index = 0; index < pts; ++index) { 181607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double foundT = intersections[0][index]; 181707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_less_than_zero(foundT) 181807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com || approximately_greater_than_one(foundT)) { 181907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 182007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1821277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkScalar testY = (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fY; 182207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_negative(testY - *bestY) 182307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com || approximately_negative(basePt.fY - testY)) { 182407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 182507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 182607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (pts > 1 && fVerb == SkPath::kLine_Verb) { 182707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; // if the intersection is edge on, wait for another one 182807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 182907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb > SkPath::kLine_Verb) { 1830277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, foundT).fX; 183107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_zero(dx)) { 183207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; // hit vertical, wait for another one 183307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 183407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 183507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *bestY = testY; 183607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bestT = foundT; 183707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 183807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (bestT < 0) { 183907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 184007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 184107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(bestT >= 0); 184207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(bestT <= 1); 184307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int start; 184407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int end = 0; 184507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 184607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com start = end; 184707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com end = nextSpan(start, 1); 184807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (fTs[end].fT < bestT); 184907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: see next candidate for a better pattern to find the next start/end pair 185007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (start + 1 < end && fTs[start].fDone) { 185107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++start; 185207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 185307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!isCanceled(start)) { 185407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *hitT = bestT; 185507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bestTIndex = start; 185607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *hitSomething = true; 185707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 185807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return bestTIndex; 185907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 186007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 1861570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::decrementSpan(SkOpSpan* span) { 186207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span->fWindValue > 0); 186307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (--(span->fWindValue) == 0) { 186407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!span->fOppValue && !span->fDone) { 186507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 186607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++fDoneSpans; 1867570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return true; 186807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 186907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 1870570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return false; 187107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 187207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 187307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::bumpSpan(SkOpSpan* span, int windDelta, int oppDelta) { 18747eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkASSERT(!span->fDone || span->fTiny || span->fSmall); 187507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fWindValue += windDelta; 187607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span->fWindValue >= 0); 187707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOppValue += oppDelta; 187807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span->fOppValue >= 0); 187907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fXor) { 188007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fWindValue &= 1; 188107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 188207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fOppXor) { 188307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOppValue &= 1; 188407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 188507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!span->fWindValue && !span->fOppValue) { 188607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 188707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++fDoneSpans; 188807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return true; 188907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 189007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return false; 189107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 189207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 18934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpSpan& SkOpSegment::firstSpan(const SkOpSpan& thisSpan) const { 18944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* firstSpan = &thisSpan; // rewind to the start 18954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* beginSpan = fTs.begin(); 18964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& testPt = thisSpan.fPt; 18974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (firstSpan > beginSpan && firstSpan[-1].fPt == testPt) { 18984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --firstSpan; 18994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return *firstSpan; 19014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 19024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 19034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgconst SkOpSpan& SkOpSegment::lastSpan(const SkOpSpan& thisSpan) const { 19044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small 19054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* lastSpan = &thisSpan; // find the end 19064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& testPt = thisSpan.fPt; 19074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (lastSpan < endSpan && lastSpan[1].fPt == testPt) { 19084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++lastSpan; 19094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return *lastSpan; 19114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 19124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 19134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// with a loop, the comparison is move involved 19144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// scan backwards and forwards to count all matching points 19154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// (verify that there are twp scans marked as loops) 19164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// compare that against 2 matching scans for loop plus other results 19174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgbool SkOpSegment::calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts) { 19184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& firstSpan = this->firstSpan(thisSpan); // rewind to the start 19194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& lastSpan = this->lastSpan(thisSpan); // find the end 19204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double firstLoopT = -1, lastLoopT = -1; 19214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* testSpan = &firstSpan - 1; 19224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++testSpan <= &lastSpan) { 19234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (testSpan->fLoop) { 19244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstLoopT = testSpan->fT; 19254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 19264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org testSpan = &lastSpan + 1; 19294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (--testSpan >= &firstSpan) { 19304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (testSpan->fLoop) { 19314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org lastLoopT = testSpan->fT; 19324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 19334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT((firstLoopT == -1) == (lastLoopT == -1)); 19364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (firstLoopT == -1) { 19374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 19384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(firstLoopT < lastLoopT); 19404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org testSpan = &firstSpan - 1; 19414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org smallCounts[0] = smallCounts[1] = 0; 19424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++testSpan <= &lastSpan) { 19434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(approximately_equal(testSpan->fT, firstLoopT) + 19444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org approximately_equal(testSpan->fT, lastLoopT) == 1); 19454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++; 19464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 19474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 19484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 19494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 1950dac1d17027dcaa5596885a9f333979418b35001ccaryclarkdouble SkOpSegment::calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, double max, 1951dac1d17027dcaa5596885a9f333979418b35001ccaryclark double hiEnd, const SkOpSegment* other, int thisStart) { 1952dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (max >= hiEnd) { 1953dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 1954dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1955dac1d17027dcaa5596885a9f333979418b35001ccaryclark int end = findOtherT(hiEnd, ref); 1956dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (end < 0) { 1957dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 1958dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1959dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tHi = span(end).fT; 1960dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tLo, refLo; 1961dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (thisStart >= 0) { 1962dac1d17027dcaa5596885a9f333979418b35001ccaryclark tLo = span(thisStart).fT; 1963dac1d17027dcaa5596885a9f333979418b35001ccaryclark refLo = min; 1964dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1965dac1d17027dcaa5596885a9f333979418b35001ccaryclark int start1 = findOtherT(loEnd, ref); 1966dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(start1 >= 0); 1967dac1d17027dcaa5596885a9f333979418b35001ccaryclark tLo = span(start1).fT; 1968dac1d17027dcaa5596885a9f333979418b35001ccaryclark refLo = loEnd; 1969dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1970dac1d17027dcaa5596885a9f333979418b35001ccaryclark double missingT = (max - refLo) / (hiEnd - refLo); 1971dac1d17027dcaa5596885a9f333979418b35001ccaryclark missingT = tLo + missingT * (tHi - tLo); 1972dac1d17027dcaa5596885a9f333979418b35001ccaryclark return missingT; 1973dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 1974dac1d17027dcaa5596885a9f333979418b35001ccaryclark 1975dac1d17027dcaa5596885a9f333979418b35001ccaryclarkdouble SkOpSegment::calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, double max, 1976dac1d17027dcaa5596885a9f333979418b35001ccaryclark double hiEnd, const SkOpSegment* other, int thisEnd) { 1977dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (min <= loEnd) { 1978dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 1979dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1980dac1d17027dcaa5596885a9f333979418b35001ccaryclark int start = findOtherT(loEnd, ref); 1981dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (start < 0) { 1982dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 1983dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1984dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tLo = span(start).fT; 1985dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tHi, refHi; 1986dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (thisEnd >= 0) { 1987dac1d17027dcaa5596885a9f333979418b35001ccaryclark tHi = span(thisEnd).fT; 1988dac1d17027dcaa5596885a9f333979418b35001ccaryclark refHi = max; 1989dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 1990dac1d17027dcaa5596885a9f333979418b35001ccaryclark int end1 = findOtherT(hiEnd, ref); 1991dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (end1 < 0) { 1992dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 1993dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1994dac1d17027dcaa5596885a9f333979418b35001ccaryclark tHi = span(end1).fT; 1995dac1d17027dcaa5596885a9f333979418b35001ccaryclark refHi = hiEnd; 1996dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 1997dac1d17027dcaa5596885a9f333979418b35001ccaryclark double missingT = (min - loEnd) / (refHi - loEnd); 1998dac1d17027dcaa5596885a9f333979418b35001ccaryclark missingT = tLo + missingT * (tHi - tLo); 1999dac1d17027dcaa5596885a9f333979418b35001ccaryclark return missingT; 2000dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 2001dac1d17027dcaa5596885a9f333979418b35001ccaryclark 20024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// see if spans with two or more intersections have the same number on the other end 20034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::checkDuplicates() { 20044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 20054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 20064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index; 20074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int endIndex = 0; 20084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool endFound; 20094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 20104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index = endIndex; 20114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org endIndex = nextExactSpan(index, 1); 20124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if ((endFound = endIndex < 0)) { 20134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org endIndex = count(); 20144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int dupCount = endIndex - index; 20164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (dupCount < 2) { 20174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 20184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 20204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* thisSpan = &fTs[index]; 2021dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (thisSpan->fNear) { 2022dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2023dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 20244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = thisSpan->fOther; 20254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oIndex = thisSpan->fOtherIndex; 20264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oStart = other->nextExactSpan(oIndex, -1) + 1; 20274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oEnd = other->nextExactSpan(oIndex, 1); 20284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oEnd < 0) { 20294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oEnd = other->count(); 20304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oCount = oEnd - oStart; 20324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // force the other to match its t and this pt if not on an end point 20334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oCount != dupCount) { 20344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans.push_back(); 20354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fOther = NULL; 20364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 20374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fPt = thisSpan->fPt; 20384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpan = other->span(oIndex); 20394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oCount > dupCount) { 20404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment = this; 20414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fT = thisSpan->fT; 20424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->checkLinks(&oSpan, &missingSpans); 20434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 20444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment = other; 20454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fT = oSpan.fT; 20464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org checkLinks(thisSpan, &missingSpans); 20474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!missingSpans.back().fOther) { 20494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missingSpans.pop_back(); 20504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (++index < endIndex); 20534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (!endFound); 20544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int missingCount = missingSpans.count(); 20554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (missingCount == 0) { 20564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 20574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence; 20594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (index = 0; index < missingCount; ++index) { 20604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans[index]; 20614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* missingOther = missing.fOther; 20624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (missing.fSegment == missing.fOther) { 20634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 20644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 2065dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if 0 // FIXME: this eliminates spurious data from skpwww_argus_presse_fr_41 but breaks 2066dac1d17027dcaa5596885a9f333979418b35001ccaryclark // skpwww_fashionscandal_com_94 -- calcAngles complains, but I don't understand why 2067dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (missing.fSegment->containsT(missing.fT, missing.fOther, missing.fOtherT)) { 2068dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_DUPLICATES 2069dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("skip 1 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fSegment->fID, 2070dac1d17027dcaa5596885a9f333979418b35001ccaryclark missing.fT, missing.fOther->fID, missing.fOtherT); 2071dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 2072dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2073dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2074dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (missing.fOther->containsT(missing.fOtherT, missing.fSegment, missing.fT)) { 2075dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_DUPLICATES 2076dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("skip 2 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fOther->fID, 2077dac1d17027dcaa5596885a9f333979418b35001ccaryclark missing.fOtherT, missing.fSegment->fID, missing.fT); 2078dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 2079dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2080dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2081dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 2082dac1d17027dcaa5596885a9f333979418b35001ccaryclark // skip if adding would insert point into an existing coincindent span 2083dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (missing.fSegment->inCoincidentSpan(missing.fT, missingOther) 2084dac1d17027dcaa5596885a9f333979418b35001ccaryclark && missingOther->inCoincidentSpan(missing.fOtherT, this)) { 2085dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2086dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2087dac1d17027dcaa5596885a9f333979418b35001ccaryclark // skip if the created coincident spans are small 2088dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (missing.fSegment->coincidentSmall(missing.fPt, missing.fT, missingOther) 2089dac1d17027dcaa5596885a9f333979418b35001ccaryclark && missingOther->coincidentSmall(missing.fPt, missing.fOtherT, missing.fSegment)) { 2090dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2091dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 20924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOther, 20934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fOtherT, false, missing.fPt); 20944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (added && added->fSmall) { 20954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence); 20964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 20984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (index = 0; index < missingCount; ++index) { 20994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans[index]; 21004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->fixOtherTIndex(); 21014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fOther->fixOtherTIndex(); 21024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 21034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (index = 0; index < missingCoincidence.count(); ++index) { 21044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingCoincidence[index]; 21054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->fixOtherTIndex(); 21064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 21074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 21084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 21094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 2110fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com// look to see if the curve end intersects an intermediary that intersects the other 2111fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.comvoid SkOpSegment::checkEnds() { 21124fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com debugValidate(); 2113570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 2114fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com int count = fTs.count(); 2115fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com for (int index = 0; index < count; ++index) { 2116fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com const SkOpSpan& span = fTs[index]; 2117570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double otherT = span.fOtherT; 2118570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (otherT != 0 && otherT != 1) { // only check ends 2119fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com continue; 2120fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2121570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSegment* other = span.fOther; 2122570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // peek start/last describe the range of spans that match the other t of this span 2123fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com int peekStart = span.fOtherIndex; 2124570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (--peekStart >= 0 && other->fTs[peekStart].fT == otherT) 2125570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ; 2126570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int otherCount = other->fTs.count(); 2127fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com int peekLast = span.fOtherIndex; 2128570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (++peekLast < otherCount && other->fTs[peekLast].fT == otherT) 2129570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ; 2130570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (++peekStart == --peekLast) { // if there isn't a range, there's nothing to do 2131fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com continue; 2132fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2133570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // t start/last describe the range of spans that match the t of this span 2134fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com double t = span.fT; 2135a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double tBottom = -1; 2136a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int tStart = -1; 2137a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int tLast = count; 2138a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com bool lastSmall = false; 2139a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double afterT = t; 2140a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com for (int inner = 0; inner < count; ++inner) { 2141a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double innerT = fTs[inner].fT; 2142a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (innerT <= t && innerT > tBottom) { 2143a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (innerT < t || !lastSmall) { 2144a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com tStart = inner - 1; 2145a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2146a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com tBottom = innerT; 2147a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2148a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (innerT > afterT) { 2149a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (t == afterT && lastSmall) { 2150a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com afterT = innerT; 2151a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } else { 2152a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com tLast = inner; 2153a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com break; 2154a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2155a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2156a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com lastSmall = innerT <= t ? fTs[inner].fSmall : false; 2157fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2158fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com for (int peekIndex = peekStart; peekIndex <= peekLast; ++peekIndex) { 2159570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (peekIndex == span.fOtherIndex) { // skip the other span pointed to by this span 2160fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com continue; 2161fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2162fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com const SkOpSpan& peekSpan = other->fTs[peekIndex]; 2163fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com SkOpSegment* match = peekSpan.fOther; 21647eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (match->done()) { 21657eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com continue; // if the edge has already been eaten (likely coincidence), ignore it 21667eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 2167fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com const double matchT = peekSpan.fOtherT; 2168570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // see if any of the spans match the other spans 2169570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com for (int tIndex = tStart + 1; tIndex < tLast; ++tIndex) { 2170fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com const SkOpSpan& tSpan = fTs[tIndex]; 2171570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (tSpan.fOther == match) { 2172570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (tSpan.fOtherT == matchT) { 21737eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com goto nextPeekIndex; 2174570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2175570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double midT = (tSpan.fOtherT + matchT) / 2; 2176570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (match->betweenPoints(midT, tSpan.fPt, peekSpan.fPt)) { 21777eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com goto nextPeekIndex; 2178570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2179fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2180fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2181570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (missingSpans.count() > 0) { 2182570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const MissingSpan& lastMissing = missingSpans.back(); 2183866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org if (lastMissing.fT == t 2184570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && lastMissing.fOther == match 2185570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && lastMissing.fOtherT == matchT) { 2186570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(lastMissing.fPt == peekSpan.fPt); 2187570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2188570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2189570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2190570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_CHECK_ENDS 2191570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,%1.9g)\n", 2192570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, peekSpan.fPt.fY); 2193570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 2194fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com // this segment is missing a entry that the other contains 2195fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com // remember so we can add the missing one and recompute the indices 21967eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com { 21977eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com MissingSpan& missing = missingSpans.push_back(); 21987eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 21997eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com missing.fT = t; 220065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkASSERT(this != match); 22017eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com missing.fOther = match; 22027eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com missing.fOtherT = matchT; 22037eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com missing.fPt = peekSpan.fPt; 22047eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 22057eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com break; 22067eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.comnextPeekIndex: 22077eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com ; 22087eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 2209fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 2210570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (missingSpans.count() == 0) { 22117eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com debugValidate(); 22124fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com return; 22134fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com } 22144fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com debugValidate(); 2215570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int missingCount = missingSpans.count(); 2216fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com for (int index = 0; index < missingCount; ++index) { 2217570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com MissingSpan& missing = missingSpans[index]; 22184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (this != missing.fOther) { 22194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt); 22204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 2221fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 22224fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com fixOtherTIndex(); 2223570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // OPTIMIZATION: this may fix indices more than once. Build an array of unique segments to 2224570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // avoid this 22254fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com for (int index = 0; index < missingCount; ++index) { 2226866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org missingSpans[index].fOther->fixOtherTIndex(); 2227fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com } 22284fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com debugValidate(); 2229fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com} 2230fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com 22314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::checkLinks(const SkOpSpan* base, 22324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkTArray<MissingSpan, true>* missingSpans) const { 22334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* first = fTs.begin(); 22344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* last = fTs.end() - 1; 22354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(base >= first && last >= base); 22364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSegment* other = base->fOther; 22374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oFirst = other->fTs.begin(); 22384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oLast = other->fTs.end() - 1; 22394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oSpan = &other->fTs[base->fOtherIndex]; 22404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* test = base; 22414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* missing = NULL; 22424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (test > first && (--test)->fPt == base->fPt) { 224365b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (this == test->fOther) { 224465b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark continue; 224565b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 22464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); 22474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org test = base; 22494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (test < last && (++test)->fPt == base->fPt) { 225065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkASSERT(this != test->fOther); 22514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); 22524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 22544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 22554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// see if spans with two or more intersections all agree on common t and point values 22564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::checkMultiples() { 22574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 22584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index; 22594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int end = 0; 22604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (fTs[++end].fT == 0) 22614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ; 22624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (fTs[end].fT < 1) { 22634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int start = index = end; 22644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org end = nextExactSpan(index, 1); 22654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (end <= index) { 22664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; // buffer overflow example triggers this 22674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (index + 1 == end) { 22694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 22704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // force the duplicates to agree on t and pt if not on the end 2272dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& span = fTs[index]; 2273dac1d17027dcaa5596885a9f333979418b35001ccaryclark double thisT = span.fT; 2274dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkPoint& thisPt = span.fPt; 2275dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fMultiple = true; 22764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool aligned = false; 22774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++index < end) { 22784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org aligned |= alignSpan(index, thisT, thisPt); 22794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (aligned) { 22814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org alignSpanState(start, end); 22824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 2283dac1d17027dcaa5596885a9f333979418b35001ccaryclark fMultiples = true; 22844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 22864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 22874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 22884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, 22894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingPtr, 22904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkTArray<MissingSpan, true>* missingSpans) { 22914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(oSpan->fPt == test->fPt); 22924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oTest = oSpan; 22934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (oTest > oFirst && (--oTest)->fPt == test->fPt) { 22944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) { 22954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 22964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 22984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oTest = oSpan; 22994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (oTest < oLast && (++oTest)->fPt == test->fPt) { 23004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) { 23014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 23024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (*missingPtr) { 23054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missingSpans->push_back(); 23064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& lastMissing = missingSpans->back(); 23084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (*missingPtr) { 23094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org lastMissing = missingSpans->end()[-2]; 23104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *missingPtr = test; 23124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org lastMissing.fOther = test->fOther; 23134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org lastMissing.fOtherT = test->fOtherT; 23144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 23154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 2316570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::checkSmall(int index) const { 2317570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (fTs[index].fSmall) { 231807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return true; 231907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2320570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double tBase = fTs[index].fT; 2321570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (index > 0 && precisely_negative(tBase - fTs[--index].fT)) 2322570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com ; 2323570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return fTs[index].fSmall; 2324570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 2325570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 23264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// a pair of curves may turn into coincident lines -- small may be a hint that that happened 23274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// if a cubic contains a loop, the counts must be adjusted 23284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::checkSmall() { 23294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 23304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* beginSpan = fTs.begin(); 23314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* thisSpan = beginSpan - 1; 23324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small 23334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++thisSpan < endSpan) { 23344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!thisSpan->fSmall) { 23354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 23364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!thisSpan->fWindValue) { 23384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 23394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& firstSpan = this->firstSpan(*thisSpan); 23414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& lastSpan = this->lastSpan(*thisSpan); 23425e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark const SkOpSpan* nextSpan = &firstSpan + 1; 23434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ptrdiff_t smallCount = &lastSpan - &firstSpan + 1; 23444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(1 <= smallCount && smallCount < count()); 23455e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark if (smallCount <= 1 && !nextSpan->fSmall) { 23464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(1 == smallCount); 23474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org checkSmallCoincidence(firstSpan, NULL); 23484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 23494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // at this point, check for missing computed intersections 23514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& testPt = firstSpan.fPt; 23524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org thisSpan = &firstSpan - 1; 23534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = NULL; 23544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++thisSpan <= &lastSpan) { 23554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other = thisSpan->fOther; 23564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (other != this) { 23574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 23584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(other != this); 23614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oIndex = thisSpan->fOtherIndex; 23624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpan = other->span(oIndex); 23634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oFirstSpan = other->firstSpan(oSpan); 23644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oLastSpan = other->lastSpan(oSpan); 23654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ptrdiff_t oCount = &oLastSpan - &oFirstSpan + 1; 23664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (fLoop) { 23674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int smallCounts[2]; 23684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!other->fLoop); // FIXME: we need more complicated logic for pair of loops 23694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (calcLoopSpanCount(*thisSpan, smallCounts)) { 23704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (smallCounts[0] && oCount != smallCounts[0]) { 23714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(0); // FIXME: need a working test case to properly code & debug 23724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (smallCounts[1] && oCount != smallCounts[1]) { 23744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(0); // FIXME: need a working test case to properly code & debug 23754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org goto nextSmallCheck; 23774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (other->fLoop) { 23804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int otherCounts[2]; 23814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (other->calcLoopSpanCount(other->span(oIndex), otherCounts)) { 23824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (otherCounts[0] && otherCounts[0] != smallCount) { 23834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(0); // FIXME: need a working test case to properly code & debug 23844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (otherCounts[1] && otherCounts[1] != smallCount) { 23864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(0); // FIXME: need a working test case to properly code & debug 23874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org goto nextSmallCheck; 23894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 23914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oCount != smallCount) { // check if number of pts in this match other 23924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans.push_back(); 23934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fOther = NULL; 23944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 23954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fPt = testPt; 23964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpan = other->span(oIndex); 23974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oCount > smallCount) { 23984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment = this; 23994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fT = thisSpan->fT; 24004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->checkLinks(&oSpan, &missingSpans); 24014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 24024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment = other; 24034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fT = oSpan.fT; 24044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org checkLinks(thisSpan, &missingSpans); 24054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!missingSpans.back().fOther || missing.fSegment->done()) { 24074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missingSpans.pop_back(); 24084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgnextSmallCheck: 24114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org thisSpan = &lastSpan; 24124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int missingCount = missingSpans.count(); 24144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < missingCount; ++index) { 24154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans[index]; 24164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* missingOther = missing.fOther; 24174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid 24184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOtherT, false, 24194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fPt)) { 24204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 24214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24228cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, missing.fSegment); 24234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& otherSpan = missingOther->span(otherTIndex); 24244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (otherSpan.fSmall) { 24254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* nextSpan = &otherSpan; 24264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 24274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++nextSpan; 24284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (nextSpan->fSmall); 2429630240d18805faf81d8e75172496ad165c2226b2caryclark SkAssertResult(missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, 2430630240d18805faf81d8e75172496ad165c2226b2caryclark nextSpan->fT, missingOther)); 24314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else if (otherSpan.fT > 0) { 24324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* priorSpan = &otherSpan; 24334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 24344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org --priorSpan; 24354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (priorSpan->fT == otherSpan.fT); 24364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (priorSpan->fSmall) { 24374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missingOther); 24384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // OPTIMIZATION: this may fix indices more than once. Build an array of unique segments to 24424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // avoid this 24434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < missingCount; ++index) { 24444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan& missing = missingSpans[index]; 24454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->fixOtherTIndex(); 24464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fOther->fixOtherTIndex(); 24474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 24494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 24504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 24514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::checkSmallCoincidence(const SkOpSpan& span, 24524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkTArray<MissingSpan, true>* checkMultiple) { 24534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(span.fSmall); 24548cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (0 && !span.fWindValue) { 24558cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return; 24568cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 24574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(&span < fTs.end() - 1); 24584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* next = &span + 1; 24594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!next->fSmall || checkMultiple); 24604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (checkMultiple) { 24614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (next->fSmall) { 24624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++next; 24634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(next < fTs.end()); 24644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = span.fOther; 24674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (other != next->fOther) { 24684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!checkMultiple) { 24694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 24704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* test = next + 1; 24724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (test == fTs.end()) { 24734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 24744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (test->fPt != next->fPt || !precisely_equal(test->fT, next->fT)) { 24764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 24774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org next = test; 24794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(span.fT < next->fT); 24814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oStartIndex = other->findExactT(span.fOtherT, this); 24824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oEndIndex = other->findExactT(next->fOtherT, this); 24834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // FIXME: be overly conservative by limiting this to the caller that allows multiple smalls 24844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!checkMultiple || fVerb != SkPath::kLine_Verb || other->fVerb != SkPath::kLine_Verb) { 24854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPoint mid = ptAtT((span.fT + next->fT) / 2); 24864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpanStart = other->fTs[oStartIndex]; 24874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpanEnd = other->fTs[oEndIndex]; 24884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPoint oMid = other->ptAtT((oSpanStart.fT + oSpanEnd.fT) / 2); 24894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!SkDPoint::ApproximatelyEqual(mid, oMid)) { 24904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 24914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 24934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // FIXME: again, be overly conservative to avoid breaking existing tests 24944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& oSpan = oStartIndex < oEndIndex ? other->fTs[oStartIndex] 24954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org : other->fTs[oEndIndex]; 24964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (checkMultiple && !oSpan.fSmall) { 24974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 24984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 249965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// SkASSERT(oSpan.fSmall); 25004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oStartIndex < oEndIndex) { 2501630240d18805faf81d8e75172496ad165c2226b2caryclark SkAssertResult(addTCoincident(span.fPt, next->fPt, next->fT, other)); 25024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 25034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addTCancel(span.fPt, next->fPt, other); 25044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!checkMultiple) { 25064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 25074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // check to see if either segment is coincident with a third segment -- if it is, and if 25094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // the opposite segment is not already coincident with the third, make it so 25104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // OPTIMIZE: to make this check easier, add coincident and cancel could set a coincident bit 25114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span.fWindValue != 1 || span.fOppValue != 0) { 25124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// start here; 25134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // iterate through the spans, looking for the third coincident case 25144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // if we find one, we need to return state to the caller so that the indices can be fixed 25154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // this also suggests that all of this function is fragile since it relies on a valid index 25164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // probably should make this a common function rather than copy/paste code 25184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oSpan.fWindValue != 1 || oSpan.fOppValue != 0) { 25194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* oTest = &oSpan; 25204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (--oTest >= other->fTs.begin()) { 25214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT)) { 25224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 25234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* testOther = oTest->fOther; 25254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(testOther != this); 25264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // look in both directions to see if there is a coincident span 25274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* tTest = testOther->fTs.begin(); 25284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int testIndex = 0; testIndex < testOther->count(); ++testIndex) { 25294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (tTest->fPt != span.fPt) { 25304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++tTest; 25314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 25324431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (testOther->verb() != SkPath::kLine_Verb 25344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org || other->verb() != SkPath::kLine_Verb) { 25354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPoint mid = ptAtT((span.fT + next->fT) / 2); 25364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPoint oMid = other->ptAtT((oTest->fOtherT + tTest->fT) / 2); 25374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!SkDPoint::ApproximatelyEqual(mid, oMid)) { 25384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 25394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 2540a1ed7aec95eb8c77d1a39834fea476780007cadeskia.committer@gmail.com } 25414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_CONCIDENT 25424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s coincident found=%d %1.9g %1.9g\n", __FUNCTION__, testOther->fID, 25434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oTest->fOtherT, tTest->fT); 25444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 25454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (tTest->fT < oTest->fOtherT) { 2546630240d18805faf81d8e75172496ad165c2226b2caryclark SkAssertResult(addTCoincident(span.fPt, next->fPt, next->fT, testOther)); 25474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 25484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org addTCancel(span.fPt, next->fPt, testOther); 25494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org MissingSpan missing; 25514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment = testOther; 25524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org checkMultiple->push_back(missing); 25534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 25544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org oTest = &oSpan; 25574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++oTest < other->fTs.end()) { 25584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT)) { 25594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 25604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 25624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 25644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 25654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 2566570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// if pair of spans on either side of tiny have the same end point and mid point, mark 2567570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// them as parallel 2568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::checkTiny() { 2569570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; 2570570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* thisSpan = fTs.begin() - 1; 2571570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan* endSpan = fTs.end() - 1; // last can't be tiny 2572570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (++thisSpan < endSpan) { 2573570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!thisSpan->fTiny) { 2574570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2575570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2576570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* nextSpan = thisSpan + 1; 2577570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double thisT = thisSpan->fT; 2578570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double nextT = nextSpan->fT; 2579570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (thisT == nextT) { 2580570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2581570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2582570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(thisT < nextT); 2583570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(thisSpan->fPt == nextSpan->fPt); 2584570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* thisOther = thisSpan->fOther; 2585570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSegment* nextOther = nextSpan->fOther; 2586570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int oIndex = thisSpan->fOtherIndex; 2587570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com for (int oStep = -1; oStep <= 1; oStep += 2) { 2588570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int oEnd = thisOther->nextExactSpan(oIndex, oStep); 2589570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (oEnd < 0) { 2590570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2591570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2592570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& oSpan = thisOther->span(oEnd); 2593570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int nIndex = nextSpan->fOtherIndex; 2594570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com for (int nStep = -1; nStep <= 1; nStep += 2) { 2595570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int nEnd = nextOther->nextExactSpan(nIndex, nStep); 2596570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (nEnd < 0) { 2597570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2598570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2599570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& nSpan = nextOther->span(nEnd); 2600570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (oSpan.fPt != nSpan.fPt) { 2601570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2602570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2603570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double oMidT = (thisSpan->fOtherT + oSpan.fT) / 2; 2604570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint& oPt = thisOther->ptAtT(oMidT); 2605570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com double nMidT = (nextSpan->fOtherT + nSpan.fT) / 2; 2606570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint& nPt = nextOther->ptAtT(nMidT); 2607570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!AlmostEqualUlps(oPt, nPt)) { 2608570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 2609570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2610570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_CHECK_TINY 2611570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDebugf("%s [%d] add coincidence [%d] [%d]\n", __FUNCTION__, fID, 2612570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com thisOther->fID, nextOther->fID); 2613570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 2614570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // this segment is missing a entry that the other contains 2615570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com // remember so we can add the missing one and recompute the indices 2616570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com MissingSpan& missing = missingSpans.push_back(); 2617570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); 2618570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fSegment = thisOther; 2619570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fT = thisSpan->fOtherT; 262065b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark SkASSERT(this != nextOther); 2621570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fOther = nextOther; 2622570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fOtherT = nextSpan->fOtherT; 2623570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fPt = thisSpan->fPt; 2624570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2625570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2626570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2627570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int missingCount = missingSpans.count(); 2628570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!missingCount) { 2629570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return; 2630570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2631570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com for (int index = 0; index < missingCount; ++index) { 2632570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com MissingSpan& missing = missingSpans[index]; 26334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (missing.fSegment != missing.fOther) { 26344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fSegment->addTPair(missing.fT, missing.fOther, missing.fOtherT, false, 26354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org missing.fPt); 26364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 2637570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 26384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // OPTIMIZE: consolidate to avoid multiple calls to fix index 2639570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com for (int index = 0; index < missingCount; ++index) { 2640570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com MissingSpan& missing = missingSpans[index]; 2641570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fSegment->fixOtherTIndex(); 2642570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com missing.fOther->fixOtherTIndex(); 264307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 264407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 264507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 2646dac1d17027dcaa5596885a9f333979418b35001ccaryclarkbool SkOpSegment::coincidentSmall(const SkPoint& pt, double t, const SkOpSegment* other) const { 2647dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 2648dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 2649dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = this->span(index); 2650dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fOther != other) { 2651dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2652dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2653dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fPt == pt) { 2654dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2655dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2656dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!AlmostEqualUlps(span.fPt, pt)) { 2657dac1d17027dcaa5596885a9f333979418b35001ccaryclark continue; 2658dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2659dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (fVerb != SkPath::kCubic_Verb) { 2660dac1d17027dcaa5596885a9f333979418b35001ccaryclark return true; 2661dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2662dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tInterval = t - span.fT; 2663dac1d17027dcaa5596885a9f333979418b35001ccaryclark double tMid = t - tInterval / 2; 2664dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDPoint midPt = dcubic_xy_at_t(fPts, tMid); 2665dac1d17027dcaa5596885a9f333979418b35001ccaryclark return midPt.approximatelyEqual(xyAtT(t)); 2666dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 2667dac1d17027dcaa5596885a9f333979418b35001ccaryclark return false; 2668dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 2669dac1d17027dcaa5596885a9f333979418b35001ccaryclark 2670a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.combool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, 2671a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) const { 2672a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkASSERT(span->fT == 0 || span->fT == 1); 2673a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkASSERT(span->fOtherT == 0 || span->fOtherT == 1); 2674a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan* otherSpan = &other->span(oEnd); 2675a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double refT = otherSpan->fT; 2676a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkPoint& refPt = otherSpan->fPt; 2677a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan* lastSpan = &other->span(step > 0 ? other->count() - 1 : 0); 2678a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com do { 2679a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSegment* match = span->fOther; 2680a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (match == otherSpan->fOther) { 2681a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com // find start of respective spans and see if both have winding 2682a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int startIndex, endIndex; 2683a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (span->fOtherT == 1) { 2684a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com endIndex = span->fOtherIndex; 2685a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com startIndex = match->nextExactSpan(endIndex, -1); 2686a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } else { 2687a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com startIndex = span->fOtherIndex; 2688a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com endIndex = match->nextExactSpan(startIndex, 1); 2689a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2690a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan& startSpan = match->span(startIndex); 2691a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (startSpan.fWindValue != 0) { 2692a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com // draw ray from endSpan.fPt perpendicular to end tangent and measure distance 2693a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com // to other segment. 2694a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan& endSpan = match->span(endIndex); 2695a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkDLine ray; 2696a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkVector dxdy; 2697a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (span->fOtherT == 1) { 2698a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com ray.fPts[0].set(startSpan.fPt); 2699a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com dxdy = match->dxdy(startIndex); 2700a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } else { 2701a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com ray.fPts[0].set(endSpan.fPt); 2702a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com dxdy = match->dxdy(endIndex); 2703a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2704a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com ray.fPts[1].fX = ray.fPts[0].fX + dxdy.fY; 2705a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com ray.fPts[1].fY = ray.fPts[0].fY - dxdy.fX; 2706a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkIntersections i; 2707a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int roots = (i.*CurveRay[SkPathOpsVerbToPoints(other->verb())])(other->pts(), ray); 2708a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com for (int index = 0; index < roots; ++index) { 2709a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (ray.fPts[0].approximatelyEqual(i.pt(index))) { 2710a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double matchMidT = (match->span(startIndex).fT 2711a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com + match->span(endIndex).fT) / 2; 2712a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkPoint matchMidPt = match->ptAtT(matchMidT); 2713a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com double otherMidT = (i[0][index] + other->span(oStart).fT) / 2; 2714a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkPoint otherMidPt = other->ptAtT(otherMidT); 2715a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (SkDPoint::ApproximatelyEqual(matchMidPt, otherMidPt)) { 2716a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com *startPt = startSpan.fPt; 2717a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com *endPt = endSpan.fPt; 2718a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com *endT = endSpan.fT; 2719a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return true; 2720a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2721a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2722a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2723a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2724a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 2725a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2726a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (otherSpan == lastSpan) { 2727a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com break; 2728a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 2729a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com otherSpan += step; 2730a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } while (otherSpan->fT == refT || otherSpan->fPt == refPt); 2731a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 2732a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 2733a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 27344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::findEndSpan(int endIndex) const { 27354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* span = &fTs[--endIndex]; 27364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& lastPt = span->fPt; 27374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double endT = span->fT; 27384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 27394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org span = &fTs[--endIndex]; 27404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (SkDPoint::ApproximatelyEqual(span->fPt, lastPt) && (span->fT == endT || span->fTiny)); 27414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return endIndex + 1; 27424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 27434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 274407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 274507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The M and S variable name parts stand for the operators. 274607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Mi stands for Minuend (see wiki subtraction, analogous to difference) 274707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Su stands for Subtrahend 274807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com The Opp variable name part designates that the value is for the Opposite operator. 274907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com Opposite values result from combining coincident spans. 275007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */ 275107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd, 275207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool* unsortable, SkPathOp op, const int xorMiMask, 275307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int xorSuMask) { 275407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int startIndex = *nextStart; 275507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int endIndex = *nextEnd; 275607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex != endIndex); 275707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(const int count = fTs.count()); 275807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2759dac1d17027dcaa5596885a9f333979418b35001ccaryclark int step = SkSign32(endIndex - startIndex); 2760dac1d17027dcaa5596885a9f333979418b35001ccaryclark *nextStart = startIndex; 2761dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other = isSimple(nextStart, &step); 2762dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (other) 2763dac1d17027dcaa5596885a9f333979418b35001ccaryclark { 276407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 276507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 276607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 276707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 276807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 276907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(startIndex, endIndex); 277007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fTs[min].fDone) { 277107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 277207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 277307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneBinary(min); 277407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double startT = other->fTs[*nextStart].fT; 277507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = *nextStart; 277607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 277707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd += step; 2778570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 277907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2780cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 278107e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com *unsortable = true; 2782cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return NULL; 2783cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 278407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 278507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2786dac1d17027dcaa5596885a9f333979418b35001ccaryclark const int end = nextExactSpan(startIndex, step); 2787dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(end >= 0); 278807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex - endIndex != 0); 278907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 27904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 27914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 27924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp); 2793570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 27944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!sortable) { 27957eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com *unsortable = true; 27968cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneBinary(SkMin32(startIndex, endIndex)); 27977eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com return NULL; 27987eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 27994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* angle = spanToAngle(end, startIndex); 28004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (angle->unorderable()) { 280107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 28028cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneBinary(SkMin32(startIndex, endIndex)); 280307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 280407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 28054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 28064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 28074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 280807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 280907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumMiWinding = updateWinding(endIndex, startIndex); 28108cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (sumMiWinding == SK_MinS32) { 28118cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = true; 28128cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneBinary(SkMin32(startIndex, endIndex)); 28138cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return NULL; 28148cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 281507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumSuWinding = updateOppWinding(endIndex, startIndex); 281607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 281707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap<int>(sumMiWinding, sumSuWinding); 281807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 28194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 282007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 282107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 282207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // iterate through the angle, and compute everyone's winding 282307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 282407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 282507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 282607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 282707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(), 28284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle->end(), op, &sumMiWinding, &sumSuWinding); 282907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 283007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 283107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 2832cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (nextSegment->isTiny(nextAngle)) { 283307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 28348cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneBinary(SkMin32(startIndex, endIndex)); 283507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 283607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 283707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 2838570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com foundDone = nextSegment->done(nextAngle); 283907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 284007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 284107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 284207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 284307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2844570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (nextSegment->isTiny(nextAngle)) { 284507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 284607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2847570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 2848dac1d17027dcaa5596885a9f333979418b35001ccaryclark (void) nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->end()); 2849570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2850570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* last = nextAngle->lastMarked(); 285107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 28524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 285307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 285407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 2855570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__, 2856570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last->fWindSum, 2857570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last->fSmall); 285807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 285907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 28604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 28614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 28624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (foundAngle) { 28634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org foundAngle->debugSameAs(foundAngle); 28644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 28654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 28664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 286707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneBinary(SkMin32(startIndex, endIndex)); 286807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 286907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 287007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 287107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 287207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 287307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 287407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 287507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 287607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 287707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 287807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 287907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 288007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 288107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, 288207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int* nextEnd, bool* unsortable) { 288307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int startIndex = *nextStart; 288407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int endIndex = *nextEnd; 288507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex != endIndex); 288607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(const int count = fTs.count()); 288707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 2888dac1d17027dcaa5596885a9f333979418b35001ccaryclark int step = SkSign32(endIndex - startIndex); 2889dac1d17027dcaa5596885a9f333979418b35001ccaryclark *nextStart = startIndex; 2890dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other = isSimple(nextStart, &step); 2891dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (other) 2892dac1d17027dcaa5596885a9f333979418b35001ccaryclark { 289307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // mark the smaller of startIndex, endIndex done, and all adjacent 289407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // spans with the same T value (but not 'other' spans) 289507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 289607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 289707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 289807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(startIndex, endIndex); 289907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fTs[min].fDone) { 290007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 290107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 290207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneUnary(min); 290307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double startT = other->fTs[*nextStart].fT; 290407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = *nextStart; 290507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 290607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd += step; 2907570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 290807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 2909570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (other->isTiny(SkMin32(*nextStart, *nextEnd))) { 2910570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com *unsortable = true; 2911570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return NULL; 2912570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 291307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 291407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2915dac1d17027dcaa5596885a9f333979418b35001ccaryclark const int end = nextExactSpan(startIndex, step); 2916dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(end >= 0); 291707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex - endIndex != 0); 291807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 29194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // more than one viable candidate -- measure angles to find best 29204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 29214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding); 2922570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool sortable = calcWinding != SK_NaN32; 292307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!sortable) { 292407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 29258cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneUnary(SkMin32(startIndex, endIndex)); 292607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 292707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 29284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* angle = spanToAngle(end, startIndex); 29294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 29304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 29314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 293207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 293307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int sumWinding = updateWinding(endIndex, startIndex); 29344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 293507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 293607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 293707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 293807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 293907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 294007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 294107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(), 29424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org &sumWinding); 294307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (activeAngle) { 294407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 294507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 2946cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (nextSegment->isTiny(nextAngle)) { 294707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 29488cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org markDoneUnary(SkMin32(startIndex, endIndex)); 294907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 295007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 295107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 295207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundDone = nextSegment->done(nextAngle); 295307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 295407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 295507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextSegment->done()) { 295607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 295707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2958570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (nextSegment->isTiny(nextAngle)) { 295907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 296007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 2961570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (!activeAngle) { 2962570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com nextSegment->markAndChaseDoneUnary(nextAngle->start(), nextAngle->end()); 2963570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 2964570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkOpSpan* last = nextAngle->lastMarked(); 296507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (last) { 29664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last)); 296707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *chase->append() = last; 296807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 2969570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__, 2970570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last->fOther->fTs[last->fOtherIndex].fOther->debugID(), last->fWindSum, 2971570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com last->fSmall); 297207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 297307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 29744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while ((nextAngle = nextAngle->next()) != angle); 297507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneUnary(SkMin32(startIndex, endIndex)); 297607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 297707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 297807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 297907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 298007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 298107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 298207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 298307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 298407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 298507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 298607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 298707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 298807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 298907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsortable) { 299007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int startIndex = *nextStart; 299107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int endIndex = *nextEnd; 299207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex != endIndex); 299307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(int count = fTs.count()); 2994570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0); 299507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = SkSign32(endIndex - startIndex); 29964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// Detect cases where all the ends canceled out (e.g., 2997dac1d17027dcaa5596885a9f333979418b35001ccaryclark// there is no angle) and therefore there's only one valid connection 2998dac1d17027dcaa5596885a9f333979418b35001ccaryclark *nextStart = startIndex; 2999dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other = isSimple(nextStart, &step); 3000dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (other) 3001dac1d17027dcaa5596885a9f333979418b35001ccaryclark { 300207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 300307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s simple\n", __FUNCTION__); 300407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 300507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(startIndex, endIndex); 300607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fTs[min].fDone) { 300707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 300807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 300907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDone(min, 1); 301007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double startT = other->fTs[*nextStart].fT; 301107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: I don't know why the logic here is difference from the winding case 301207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(bool firstLoop = true;) 301307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if ((approximately_less_than_zero(startT) && step < 0) 301407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com || (approximately_greater_than_one(startT) && step > 0)) { 301507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com step = -step; 301607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(firstLoop = false;) 301707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 301807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 301907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = *nextStart; 302007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 302107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd += step; 3022570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } while (precisely_zero(startT - other->fTs[*nextEnd].fT)); 302307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->fTs[SkMin32(*nextStart, *nextEnd)].fWindValue) { 302407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 302507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 302607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(firstLoop); 302707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(firstLoop = false;) 302807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com step = -step; 302907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (true); 303007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count()); 303107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 303207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 303307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(startIndex - endIndex != 0); 30344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT((startIndex - endIndex < 0) ^ (step < 0)); 30354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // parallel block above with presorted version 3036dac1d17027dcaa5596885a9f333979418b35001ccaryclark int end = nextExactSpan(startIndex, step); 3037dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(end >= 0); 30384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* angle = spanToAngle(end, startIndex); 30394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(angle); 30404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 30414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 30424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle->debugLoop(); 3043570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 30444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* nextAngle = angle->next(); 304507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpAngle* foundAngle = NULL; 304607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com bool foundDone = false; 304707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* nextSegment; 304807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int activeCount = 0; 304907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 305007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = nextAngle->segment(); 305107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++activeCount; 305207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle || (foundDone && activeCount & 1)) { 3053cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (nextSegment->isTiny(nextAngle)) { 305407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *unsortable = true; 305507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 305607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 305707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com foundAngle = nextAngle; 30584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!(foundDone = nextSegment->done(nextAngle))) { 30594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 30604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 306107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 30624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextAngle = nextAngle->next(); 30634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (nextAngle != angle); 306407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDone(SkMin32(startIndex, endIndex), 1); 306507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!foundAngle) { 306607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 306707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 306807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextStart = foundAngle->start(); 306907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *nextEnd = foundAngle->end(); 307007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextSegment = foundAngle->segment(); 307107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING 307207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n", 307307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com __FUNCTION__, debugID(), nextSegment->debugID(), *nextStart, *nextEnd); 307407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 307507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return nextSegment; 307607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 307707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 30784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::findStartSpan(int startIndex) const { 30794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = startIndex; 30804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan* span = &fTs[index]; 30814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkPoint& firstPt = span->fPt; 30824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org double firstT = span->fT; 3083dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan* prior; 30844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 3085dac1d17027dcaa5596885a9f333979418b35001ccaryclark prior = span; 3086dac1d17027dcaa5596885a9f333979418b35001ccaryclark span = &fTs[++index]; 3087dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (SkDPoint::ApproximatelyEqual(span->fPt, firstPt) 3088dac1d17027dcaa5596885a9f333979418b35001ccaryclark && (span->fT == firstT || prior->fTiny)); 30894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return index; 309007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 309107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 30924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::findExactT(double t, const SkOpSegment* match) const { 3093a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int count = this->count(); 3094a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com for (int index = 0; index < count; ++index) { 3095a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan& span = fTs[index]; 3096a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (span.fT == t && span.fOther == match) { 3097a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return index; 3098a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 3099a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 3100a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkASSERT(0); 3101a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return -1; 3102a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 3103a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 3104dac1d17027dcaa5596885a9f333979418b35001ccaryclarkint SkOpSegment::findOtherT(double t, const SkOpSegment* match) const { 3105dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 3106dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 3107dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = fTs[index]; 3108dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fOtherT == t && span.fOther == match) { 3109dac1d17027dcaa5596885a9f333979418b35001ccaryclark return index; 3110dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3111dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3112dac1d17027dcaa5596885a9f333979418b35001ccaryclark return -1; 3113dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 3114dac1d17027dcaa5596885a9f333979418b35001ccaryclark 31158cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.orgint SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) const { 31164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int count = this->count(); 31175e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark // prefer exact matches over approximate matches 31185e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark for (int index = 0; index < count; ++index) { 31195e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark const SkOpSpan& span = fTs[index]; 31205e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark if (span.fT == t && span.fOther == match) { 31215e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark return index; 31225e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } 31235e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } 31244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < count; ++index) { 31254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& span = fTs[index]; 31264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { 31274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return index; 31284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 31294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 31308cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org // Usually, the pair of ts are an exact match. It's possible that the t values have 31318cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org // been adjusted to make multiple intersections align. In this rare case, look for a 31328cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org // matching point / match pair instead. 31338cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org for (int index = 0; index < count; ++index) { 31348cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org const SkOpSpan& span = fTs[index]; 31358cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (span.fPt == pt && span.fOther == match) { 31368cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return index; 31378cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 31388cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 31394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(0); 31404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return -1; 31414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 314207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 31438cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.orgSkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsortable, 31448cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org bool firstPass) { 314507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // iterate through T intersections and return topmost 314607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // topmost tangent from y-min to first pt is closer to horizontal 314707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!done()); 314807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int firstT = -1; 31498cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org /* SkPoint topPt = */ activeLeftTop(&firstT); 315007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (firstT < 0) { 31518cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = !firstPass; 315207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com firstT = 0; 315307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (fTs[firstT].fDone) { 315407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(firstT < fTs.count()); 315507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++firstT; 315607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 315707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *tIndexPtr = firstT; 315807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *endIndexPtr = nextExactSpan(firstT, 1); 315907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return this; 316007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 316107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // sort the edges to find the leftmost 316207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = 1; 31634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int end; 31644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) { 316507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com step = -1; 316607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com end = nextSpan(firstT, step); 316707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(end != -1); 316807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 316907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // if the topmost T is not on end, or is three-way or more, find left 317007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // look for left-ness from tLeft to firstT (matching y of other) 317107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(firstT - end != 0); 31724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* markAngle = spanToAngle(firstT, end); 31734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!markAngle) { 3174dac1d17027dcaa5596885a9f333979418b35001ccaryclark markAngle = addSingletonAngles(step); 31754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 31764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org markAngle->markStops(); 3177e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle 3178e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark : markAngle->findFirst(); 31794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!baseAngle) { 31804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return NULL; // nothing to do 3181570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 318207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar top = SK_ScalarMax; 31834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpAngle* firstAngle = NULL; 31844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpAngle* angle = baseAngle; 31854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 31864431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!angle->unorderable()) { 31874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* next = angle->segment(); 31884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkPathOpsBounds bounds; 31894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org next->subDivideBounds(angle->end(), angle->start(), &bounds); 31904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (approximately_greater(top, bounds.fTop)) { 31914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org top = bounds.fTop; 31924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle = angle; 31934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 319407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 31954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = angle->next(); 31964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (angle != baseAngle); 31974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(firstAngle); 31984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 31994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s\n", __FUNCTION__); 32004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org firstAngle->debugLoop(); 320107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 320207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // skip edges that have already been processed 32034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = firstAngle; 32048cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkOpSegment* leftSegment = NULL; 32058cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org bool looped = false; 320607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 32078cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *unsortable = angle->unorderable(); 32088cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (firstPass || !*unsortable) { 32098cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org leftSegment = angle->segment(); 32108cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *tIndexPtr = angle->end(); 32118cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org *endIndexPtr = angle->start(); 32128cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone) { 32138cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org break; 32148cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 32158cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 32164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org angle = angle->next(); 32178cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org looped = true; 32188cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } while (angle != firstAngle); 32198cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (angle == firstAngle && looped) { 32208cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return NULL; 32218cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 322207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (leftSegment->verb() >= SkPath::kQuad_Verb) { 322307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int tIndex = *tIndexPtr; 322407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const int endIndex = *endIndexPtr; 3225e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark bool swap; 3226e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (!leftSegment->clockwise(tIndex, endIndex, &swap)) { 322707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #if DEBUG_SWAP_TOP 32288cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkDebugf("%s swap=%d inflections=%d serpentine=%d controlledbyends=%d monotonic=%d\n", 32298cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org __FUNCTION__, 32308cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org swap, leftSegment->debugInflections(tIndex, endIndex), 323107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com leftSegment->serpentine(tIndex, endIndex), 323207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com leftSegment->controlsContainedByEnds(tIndex, endIndex), 323307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com leftSegment->monotonicInY(tIndex, endIndex)); 323407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com #endif 323507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (swap) { 323607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not the first 323707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // sorted but merely the first not already processed (i.e., not done) 323807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkTSwap(*tIndexPtr, *endIndexPtr); 323907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 324007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 324107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 324207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fTiny); 324307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return leftSegment; 324407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 324507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 32464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgint SkOpSegment::firstActive(int tIndex) const { 32474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (fTs[tIndex].fTiny) { 32484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!isCanceled(tIndex)); 32494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org ++tIndex; 32504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 32514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return tIndex; 32524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 32534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 325407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// FIXME: not crazy about this 325507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// when the intersections are performed, the other index is into an 325607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// incomplete array. As the array grows, the indices become incorrect 325707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// while the following fixes the indices up again, it isn't smart about 325807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// skipping segments whose indices are already correct 325907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// assuming we leave the code that wrote the index in the first place 3260570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// FIXME: if called after remove, this needs to correct tiny 326107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::fixOtherTIndex() { 326207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int iCount = fTs.count(); 326307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int i = 0; i < iCount; ++i) { 326407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& iSpan = fTs[i]; 326507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double oT = iSpan.fOtherT; 326607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = iSpan.fOther; 326707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oCount = other->fTs.count(); 32684fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com SkDEBUGCODE(iSpan.fOtherIndex = -1); 326907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (int o = 0; o < oCount; ++o) { 327007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& oSpan = other->fTs[o]; 327107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan.fT) { 327207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com iSpan.fOtherIndex = o; 32734fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com oSpan.fOtherIndex = i; 327407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 327507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 327607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 32774fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com SkASSERT(iSpan.fOtherIndex >= 0); 327807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 327907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 328007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3281dac1d17027dcaa5596885a9f333979418b35001ccaryclarkbool SkOpSegment::inCoincidentSpan(double t, const SkOpSegment* other) const { 3282dac1d17027dcaa5596885a9f333979418b35001ccaryclark int foundEnds = 0; 3283dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 3284dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 3285dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& span = this->span(index); 3286dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (span.fCoincident) { 3287dac1d17027dcaa5596885a9f333979418b35001ccaryclark foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.fT)); 3288dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3289dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3290dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(foundEnds != 7); 3291dac1d17027dcaa5596885a9f333979418b35001ccaryclark return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bits set 3292dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 3293dac1d17027dcaa5596885a9f333979418b35001ccaryclark 329407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) { 329507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fDoneSpans = 0; 329607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fOperand = operand; 329707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fXor = evenOdd; 329807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fPts = pts; 329907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fVerb = verb; 3300dac1d17027dcaa5596885a9f333979418b35001ccaryclark fLoop = fMultiples = fSmall = fTiny = false; 330107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 330207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 33034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType) { 330407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int local = spanSign(start, end); 33054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (angleIncludeType == SkOpAngle::kBinarySingle) { 33064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int oppLocal = oppSign(start, end); 33074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org (void) markAndChaseWinding(start, end, local, oppLocal); 330807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // OPTIMIZATION: the reverse mark and chase could skip the first marking 33094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org (void) markAndChaseWinding(end, start, local, oppLocal); 33104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 33114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org (void) markAndChaseWinding(start, end, local); 33124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // OPTIMIZATION: the reverse mark and chase could skip the first marking 33134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org (void) markAndChaseWinding(end, start, local); 33144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 331507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 331607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 331707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/* 331807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comwhen we start with a vertical intersect, we try to use the dx to determine if the edge is to 331907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe left or the right of vertical. This determines if we need to add the span's 332007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comsign or not. However, this isn't enough. 332107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf the supplied sign (winding) is zero, then we didn't hit another vertical span, so dx is needed. 332207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comIf there was a winding, then it may or may not need adjusting. If the span the winding was borrowed 332307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comfrom has the same x direction as this span, the winding should change. If the dx is opposite, then 332407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comthe same winding is shared by both. 332507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com*/ 332607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, 332707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppWind, SkScalar hitOppDx) { 332807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(hitDx || !winding); 3329277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 333007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(dx); 333107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int windVal = windValue(SkMin32(start, end)); 333207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 3333dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, debugID(), winding, 333407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); 333507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 33364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int sideWind = winding + (dx < 0 ? windVal : -windVal); 33374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (abs(winding) < abs(sideWind)) { 33384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org winding = sideWind; 333907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 334007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDEBUGCODE(int oppLocal = oppSign(start, end)); 334107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(hitOppDx || !oppWind || !oppLocal); 334207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppWindVal = oppValue(SkMin32(start, end)); 334307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!oppWind) { 334407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWind = dx < 0 ? oppWindVal : -oppWindVal; 334507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else if (hitOppDx * dx >= 0) { 334607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); 334707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (abs(oppWind) < abs(oppSideWind)) { 334807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWind = oppSideWind; 334907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 335007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3351dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING_AT_T 3352dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind); 3353dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 335407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com (void) markAndChaseWinding(start, end, winding, oppWind); 33557eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com // OPTIMIZATION: the reverse mark and chase could skip the first marking 33567eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com (void) markAndChaseWinding(end, start, winding, oppWind); 335707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 335807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 33594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgbool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const { 33604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!baseAngle->inLoop()) { 33614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return false; 33624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 33634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = *indexPtr; 3364dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* from = fTs[index].fFromAngle; 3365dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* to = fTs[index].fToAngle; 33664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org while (++index < spanCount) { 3367dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* nextFrom = fTs[index].fFromAngle; 3368dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* nextTo = fTs[index].fToAngle; 3369dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (from != nextFrom || to != nextTo) { 33704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 33714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 33724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 33734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org *indexPtr = index; 33744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return true; 33754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 33764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 337707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// OPTIMIZE: successive calls could start were the last leaves off 337807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// or calls could specialize to walk forwards or backwards 33797eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.combool SkOpSegment::isMissing(double startT, const SkPoint& pt) const { 33804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int tCount = fTs.count(); 33814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org for (int index = 0; index < tCount; ++index) { 33827eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com const SkOpSpan& span = fTs[index]; 33837eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (approximately_zero(startT - span.fT) && pt == span.fPt) { 338407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return false; 338507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 338607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 338707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return true; 338807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 338907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3390dac1d17027dcaa5596885a9f333979418b35001ccaryclark 3391dac1d17027dcaa5596885a9f333979418b35001ccaryclarkSkOpSegment* SkOpSegment::isSimple(int* end, int* step) { 3392dac1d17027dcaa5596885a9f333979418b35001ccaryclark return nextChase(end, step, NULL, NULL); 33934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 33944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 3395a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.combool SkOpSegment::isTiny(const SkOpAngle* angle) const { 3396a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int start = angle->start(); 3397a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int end = angle->end(); 3398a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com const SkOpSpan& mSpan = fTs[SkMin32(start, end)]; 3399a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return mSpan.fTiny; 3400a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 3401a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 3402a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.combool SkOpSegment::isTiny(int index) const { 3403a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return fTs[index].fTiny; 3404a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 3405a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 3406a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com// look pair of active edges going away from coincident edge 3407a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com// one of them should be the continuation of other 3408a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com// if both are active, look to see if they both the connect to another coincident pair 34094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// if at least one is a line, then make the pair coincident 3410a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com// if neither is a line, test for coincidence 34118cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.orgbool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt, 34128cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int step, bool cancel) { 34138cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org int otherTIndex = other->findT(otherT, otherPt, this); 3414a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int next = other->nextExactSpan(otherTIndex, step); 34154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int otherMin = SkMin32(otherTIndex, next); 3416a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com int otherWind = other->span(otherMin).fWindValue; 3417a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com if (otherWind == 0) { 3418a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 3419a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 3420a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com SkASSERT(next >= 0); 3421866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org int tIndex = 0; 3422866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org do { 3423866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkOpSpan* test = &fTs[tIndex]; 3424866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkASSERT(test->fT == 0); 3425866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org if (test->fOther == other || test->fOtherT != 1) { 3426866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org continue; 3427866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org } 3428866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkPoint startPt, endPt; 3429866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org double endT; 3430866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { 3431866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkOpSegment* match = test->fOther; 3432866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org if (cancel) { 3433866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org match->addTCancel(startPt, endPt, other); 3434866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org } else { 3435630240d18805faf81d8e75172496ad165c2226b2caryclark SkAssertResult(match->addTCoincident(startPt, endPt, endT, other)); 3436a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com } 3437866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org return true; 3438866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org } 3439866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org } while (fTs[++tIndex].fT == 0); 3440a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com return false; 3441a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com} 3442a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com 344307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// this span is excluded by the winding rule -- chase the ends 344407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// as long as they are unambiguous to mark connections as done 344507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// and give them the same winding value 344607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 344707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { 344807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = SkSign32(endIndex - index); 344907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(index, endIndex); 345007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneBinary(min); 3451dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* last = NULL; 345207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 3453dac1d17027dcaa5596885a9f333979418b35001ccaryclark while ((other = other->nextChase(&index, &step, &min, &last))) { 345407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->done()) { 3455dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 3456dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 345707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 345807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->markDoneBinary(min); 345907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 346007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 346107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 346207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 346307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { 346407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = SkSign32(endIndex - index); 346507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(index, endIndex); 346607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markDoneUnary(min); 3467dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* last = NULL; 346807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 3469dac1d17027dcaa5596885a9f333979418b35001ccaryclark while ((other = other->nextChase(&index, &step, &min, &last))) { 347007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->done()) { 3471dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 3472dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 347307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 347407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->markDoneUnary(min); 347507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 347607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 347707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 347807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 34794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgSkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) { 348007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int index = angle->start(); 348107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int endIndex = angle->end(); 348207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = SkSign32(endIndex - index); 348307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(index, endIndex); 348407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markWinding(min, winding); 3485dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* last = NULL; 348607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 3487dac1d17027dcaa5596885a9f333979418b35001ccaryclark while ((other = other->nextChase(&index, &step, &min, &last))) { 348807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->fTs[min].fWindSum != SK_MinS32) { 348919eb3b2f0aa6dce5c0335230a8930e90733e5d5dcaryclark// SkASSERT(other->fTs[min].fWindSum == winding); 3490dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 3491dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 349207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 349307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com other->markWinding(min, winding); 349407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 349507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 349607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 349707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 34984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgSkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) { 34994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int min = SkMin32(index, endIndex); 35004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int step = SkSign32(endIndex - index); 35014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org markWinding(min, winding); 3502dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* last = NULL; 35034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = this; 3504dac1d17027dcaa5596885a9f333979418b35001ccaryclark while ((other = other->nextChase(&index, &step, &min, &last))) { 35054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (other->fTs[min].fWindSum != SK_MinS32) { 35064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoop); 3507dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 3508dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 35094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 35104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org other->markWinding(min, winding); 35114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 35124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return last; 35134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org} 35144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org 351507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) { 351607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int min = SkMin32(index, endIndex); 351707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int step = SkSign32(endIndex - index); 351807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markWinding(min, winding, oppWinding); 3519dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan* last = NULL; 352007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSegment* other = this; 3521dac1d17027dcaa5596885a9f333979418b35001ccaryclark while ((other = other->nextChase(&index, &step, &min, &last))) { 352207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (other->fTs[min].fWindSum != SK_MinS32) { 3523da085e6ab3b17f16a69a35c2417bebabeb5e3494caryclark#ifdef SK_DEBUG 3524dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!other->fTs[min].fLoop) { 3525dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (fOperand == other->fOperand) { 3526dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME: this is probably a bug -- rects4 asserts here 3527dac1d17027dcaa5596885a9f333979418b35001ccaryclark// SkASSERT(other->fTs[min].fWindSum == winding); 3528dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME: this is probably a bug -- rects3 asserts here 3529dac1d17027dcaa5596885a9f333979418b35001ccaryclark// SkASSERT(other->fTs[min].fOppSum == oppWinding); 3530dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 353165b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// FIXME: this is probably a bug -- issue414409b asserts here 353265b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// SkASSERT(other->fTs[min].fWindSum == oppWinding); 3533dac1d17027dcaa5596885a9f333979418b35001ccaryclark// FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here 3534dac1d17027dcaa5596885a9f333979418b35001ccaryclark// SkASSERT(other->fTs[min].fOppSum == winding); 3535dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3536dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3537dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(!last); 3538dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 3539dac1d17027dcaa5596885a9f333979418b35001ccaryclark break; 3540dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3541dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (fOperand == other->fOperand) { 3542dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->markWinding(min, winding, oppWinding); 3543dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 3544dac1d17027dcaa5596885a9f333979418b35001ccaryclark other->markWinding(min, oppWinding, winding); 354507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 354607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 354707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 354807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 354907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 355007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) { 355107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int start = angle->start(); 355207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int end = angle->end(); 355307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return markAndChaseWinding(start, end, winding, oppWinding); 355407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 355507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3556866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.orgSkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { 355707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 355807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 355907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 356007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3561866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkOpSpan* last = markAndChaseWinding(angle, maxWinding); 3562570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 3563570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 35647eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkDebugf("%s last id=%d windSum=", __FUNCTION__, 35657eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 35667eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkPathOpsDebug::WindingPrintf(last->fWindSum); 35677eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkDebugf(" small=%d\n", last->fSmall); 3568570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 3569570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 357007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 357107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 357207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 357307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding, 3574866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org int oppSumWinding, const SkOpAngle* angle) { 357507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(angle->segment() == this); 357607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (UseInnerWinding(maxWinding, sumWinding)) { 357707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com maxWinding = sumWinding; 357807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 357907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { 358007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppMaxWinding = oppSumWinding; 358107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3582866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org SkOpSpan* last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); 3583570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_WINDING 3584570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (last) { 35857eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkDebugf("%s last id=%d windSum=", __FUNCTION__, 35867eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com last->fOther->fTs[last->fOtherIndex].fOther->debugID()); 35877eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkPathOpsDebug::WindingPrintf(last->fWindSum); 35887eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com SkDebugf(" small=%d\n", last->fSmall); 3589570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 3590570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 359107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return last; 359207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 359307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 359407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// FIXME: this should also mark spans with equal (x,y) 359507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// This may be called when the segment is already marked done. While this 359607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// wastes time, it shouldn't do any more than spin through the T spans. 359707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// OPTIMIZATION: abort on first done found (assuming that this code is 359807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// always called to mark segments done). 359907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markDone(int index, int winding) { 360007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // SkASSERT(!done()); 360107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(winding); 360207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double referenceT = fTs[index].fT; 360307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 360407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 360507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDone(__FUNCTION__, lesser, winding); 360607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 360707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 360807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDone(__FUNCTION__, index, winding); 360907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); 36104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 361107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 361207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 361307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markDoneBinary(int index) { 361407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double referenceT = fTs[index].fT; 361507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 361607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 361707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDoneBinary(__FUNCTION__, lesser); 361807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 361907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 362007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDoneBinary(__FUNCTION__, index); 362107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); 36224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 362307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 362407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 362507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markDoneUnary(int index) { 362607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double referenceT = fTs[index].fT; 362707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 362807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 362907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDoneUnary(__FUNCTION__, lesser); 363007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 363107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 363207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneDoneUnary(__FUNCTION__, index); 363307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); 36344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 363507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 363607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 363707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) { 363807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* span = markOneWinding(funName, tIndex, winding); 36394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!span || span->fDone) { 364007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 364107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 364207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 364307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fDoneSpans++; 364407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 364507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 364607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { 364707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* span = verifyOneWinding(funName, tIndex); 364807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!span) { 364907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 365007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 36514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!span->fDone); 365207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 365307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fDoneSpans++; 365407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 365507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 365607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { 365707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan* span = verifyOneWindingU(funName, tIndex); 365807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!span) { 365907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return; 366007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 36614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span->fWindSum == SK_MinS32) { 36624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s uncomputed\n", __FUNCTION__); 36634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 36644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!span->fDone); 366507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 366607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com fDoneSpans++; 366707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 366807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 366907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding) { 367007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& span = fTs[tIndex]; 36714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (span.fDone && !span.fSmall) { 367207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 367307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 367407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 367507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com debugShowNewWinding(funName, span, winding); 367607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 367707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 36788cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_LIMIT_WIND_SUM 36798cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); 36808cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 368107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span.fWindSum = winding; 368207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return &span; 368307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 368407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 368507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding, 368607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppWinding) { 368707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& span = fTs[tIndex]; 36887eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (span.fDone && !span.fSmall) { 368907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 369007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 369107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 369207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com debugShowNewWinding(funName, span, winding, oppWinding); 369307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 369407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); 36958cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_LIMIT_WIND_SUM 36968cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); 36978cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 369807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span.fWindSum = winding; 369907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); 37008cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_LIMIT_WIND_SUM 37018cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM); 37028cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 370307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span.fOppSum = oppWinding; 37044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 370507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return &span; 370607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 370707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 370807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order 3709e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclarkbool SkOpSegment::clockwise(int tStart, int tEnd, bool* swap) const { 371007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(fVerb != SkPath::kLine_Verb); 371107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint edge[4]; 371207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com subDivide(tStart, tEnd, edge); 3713cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 3714cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY); 3715e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark bool sumSet = false; 371607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kCubic_Verb) { 3717e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDCubic cubic; 3718e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark cubic.set(edge); 3719e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark double inflectionTs[2]; 3720e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark int inflections = cubic.findInflections(inflectionTs); 3721e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // FIXME: this fixes cubicOp114 and breaks cubicOp58d 3722e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // the trouble is that cubics with inflections confuse whether the curve breaks towards 3723e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // or away, which in turn is used to determine if it is on the far right or left. 3724e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // Probably a totally different approach is in order. At one time I tried to project a 3725e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // horizontal ray to determine winding, but was confused by how to map the vertically 3726e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark // oriented winding computation over. 3727e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (0 && inflections) { 3728e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark double tLo = this->span(tStart).fT; 3729e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark double tHi = this->span(tEnd).fT; 3730e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark double tLoStart = tLo; 3731e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark for (int index = 0; index < inflections; ++index) { 3732e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (between(tLo, inflectionTs[index], tHi)) { 3733e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark tLo = inflectionTs[index]; 3734e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 3735e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 3736e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (tLo != tLoStart && tLo != tHi) { 3737e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDPoint sub[2]; 3738e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark sub[0] = cubic.ptAtT(tLo); 3739e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark sub[1].set(edge[3]); 3740e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDPoint ctrl[2]; 3741e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDCubic::SubDivide(fPts, sub[0], sub[1], tLo, tHi, ctrl); 3742e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark edge[0] = sub[0].asSkPoint(); 3743e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark edge[1] = ctrl[0].asSkPoint(); 3744e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark edge[2] = ctrl[1].asSkPoint(); 3745e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark sum = (edge[0].fX - edge[3].fX) * (edge[0].fY + edge[3].fY); 3746e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 3747e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 374807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY); 374907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (edge[1].fY < lesser && edge[2].fY < lesser) { 375007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1].fY} }}; 375107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDLine tangent2 = {{ {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3].fY} }}; 375207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (SkIntersections::Test(tangent1, tangent2)) { 375307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT); 375407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY); 375507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY); 3756e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark sumSet = true; 375707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 375807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 375907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3760e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (!sumSet) { 3761e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark for (int idx = 0; idx < points; ++idx){ 3762e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY); 3763e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 3764e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } 3765e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark if (fVerb == SkPath::kCubic_Verb) { 3766e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDCubic cubic; 3767e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark cubic.set(edge); 3768e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark *swap = sum > 0 && !cubic.monotonicInY() && !cubic.serpentine(); 3769e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark } else { 3770e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark SkDQuad quad; 3771e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark quad.set(edge); 3772e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark *swap = sum > 0 && !quad.monotonicInY(); 377307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 377407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return sum <= 0; 377507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 377607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 377707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::monotonicInY(int tStart, int tEnd) const { 37788cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(fVerb != SkPath::kLine_Verb); 377907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 378007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 378107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return dst.monotonicInY(); 378207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 378307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 378407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 378507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return dst.monotonicInY(); 378607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 378707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 378807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::serpentine(int tStart, int tEnd) const { 378907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb != SkPath::kCubic_Verb) { 379007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return false; 379107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 379207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT); 379307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return dst.serpentine(); 379407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 379507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 379607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::verifyOneWinding(const char* funName, int tIndex) { 379707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& span = fTs[tIndex]; 379807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (span.fDone) { 379907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 380007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 380107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 380207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum); 380307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 3804866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// If the prior angle in the sort is unorderable, the winding sum may not be computable. 3805866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// To enable the assert, the 'prior is unorderable' state could be 3806866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// piped down to this test, but not sure it's worth it. 3807866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// (Once the sort order is stored in the span, this test may be feasible.) 3808866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// SkASSERT(span.fWindSum != SK_MinS32); 3809866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// SkASSERT(span.fOppSum != SK_MinS32); 381007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return &span; 381107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 381207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 381307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) { 381407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& span = fTs[tIndex]; 381507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (span.fDone) { 381607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return NULL; 381707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 381807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE 381907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com debugShowNewWinding(funName, span, span.fWindSum); 382007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 3821866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// If the prior angle in the sort is unorderable, the winding sum may not be computable. 3822866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// To enable the assert, the 'prior is unorderable' state could be 3823866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// piped down to this test, but not sure it's worth it. 3824866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// (Once the sort order is stored in the span, this test may be feasible.) 3825866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org// SkASSERT(span.fWindSum != SK_MinS32); 382607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return &span; 382707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 382807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 382907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markWinding(int index, int winding) { 383007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// SkASSERT(!done()); 383107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(winding); 383207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double referenceT = fTs[index].fT; 383307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 383407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 383507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneWinding(__FUNCTION__, lesser, winding); 383607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 383707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 383807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneWinding(__FUNCTION__, index, winding); 383907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); 38404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 384107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 384207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 384307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::markWinding(int index, int winding, int oppWinding) { 384407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// SkASSERT(!done()); 384507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(winding || oppWinding); 384607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double referenceT = fTs[index].fT; 384707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = index; 384807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { 384907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneWinding(__FUNCTION__, lesser, winding, oppWinding); 385007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 385107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com do { 385207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com markOneWinding(__FUNCTION__, index, winding, oppWinding); 385307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); 38544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org debugValidate(); 385507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 385607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 385707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) { 385807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int nextDoorWind = SK_MaxS32; 385907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int nextOppWind = SK_MaxS32; 38604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org // prefer exact matches 386107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (tIndex > 0) { 386207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& below = fTs[tIndex - 1]; 38634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (below.fT == t) { 38644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextDoorWind = below.fWindValue; 38654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextOppWind = below.fOppValue; 38664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 38674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 38684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) { 38694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& above = fTs[tIndex + 1]; 38704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (above.fT == t) { 38714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextDoorWind = above.fWindValue; 38724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org nextOppWind = above.fOppValue; 38734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 38744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 38754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (nextDoorWind == SK_MaxS32 && tIndex > 0) { 38764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org const SkOpSpan& below = fTs[tIndex - 1]; 387707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_negative(t - below.fT)) { 387807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextDoorWind = below.fWindValue; 387907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextOppWind = below.fOppValue; 388007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 388107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 388207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) { 388307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& above = fTs[tIndex + 1]; 388407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_negative(above.fT - t)) { 388507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextDoorWind = above.fWindValue; 388607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextOppWind = above.fOppValue; 388707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 388807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 388907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextDoorWind == SK_MaxS32 && borrowWind && tIndex > 0 && t < 1) { 389007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& below = fTs[tIndex - 1]; 389107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextDoorWind = below.fWindValue; 389207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com nextOppWind = below.fOppValue; 389307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 389407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (nextDoorWind != SK_MaxS32) { 389507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkOpSpan& newSpan = fTs[tIndex]; 389607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com newSpan.fWindValue = nextDoorWind; 389707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com newSpan.fOppValue = nextOppWind; 389807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!nextDoorWind && !nextOppWind && !newSpan.fDone) { 389907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com newSpan.fDone = true; 390007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++fDoneSpans; 390107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 390207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 390307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 390407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 390507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkOpSegment::nextCandidate(int* start, int* end) const { 390607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (fTs[*end].fDone) { 390707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fTs[*end].fT == 1) { 390807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return false; 390907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 391007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++(*end); 391107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 391207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *start = *end; 391307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *end = nextExactSpan(*start, 1); 391407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return true; 391507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 391607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 3917dac1d17027dcaa5596885a9f333979418b35001ccaryclarkstatic SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) { 3918dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (last && !endSpan->fSmall) { 3919dac1d17027dcaa5596885a9f333979418b35001ccaryclark *last = endSpan; 3920dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3921dac1d17027dcaa5596885a9f333979418b35001ccaryclark return NULL; 3922dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 3923dac1d17027dcaa5596885a9f333979418b35001ccaryclark 3924dac1d17027dcaa5596885a9f333979418b35001ccaryclarkSkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, SkOpSpan** last) { 3925dac1d17027dcaa5596885a9f333979418b35001ccaryclark int origIndex = *indexPtr; 3926dac1d17027dcaa5596885a9f333979418b35001ccaryclark int step = *stepPtr; 3927dac1d17027dcaa5596885a9f333979418b35001ccaryclark int end = nextExactSpan(origIndex, step); 392807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(end >= 0); 3929dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan& endSpan = fTs[end]; 3930dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle; 3931dac1d17027dcaa5596885a9f333979418b35001ccaryclark int foundIndex; 3932dac1d17027dcaa5596885a9f333979418b35001ccaryclark int otherEnd; 3933dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other; 3934dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (angle == NULL) { 3935dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (endSpan.fT != 0 && endSpan.fT != 1) { 3936dac1d17027dcaa5596885a9f333979418b35001ccaryclark return NULL; 3937dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3938dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = endSpan.fOther; 3939dac1d17027dcaa5596885a9f333979418b35001ccaryclark foundIndex = endSpan.fOtherIndex; 3940dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherEnd = other->nextExactSpan(foundIndex, step); 3941dac1d17027dcaa5596885a9f333979418b35001ccaryclark } else { 3942dac1d17027dcaa5596885a9f333979418b35001ccaryclark int loopCount = angle->loopCount(); 3943dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (loopCount > 2) { 3944dac1d17027dcaa5596885a9f333979418b35001ccaryclark return set_last(last, &endSpan); 3945dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3946dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpAngle* next = angle->next(); 394765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (NULL == next) { 394865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 394965b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 3950dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (angle->sign() != next->sign()) { 3951dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if DEBUG_WINDING 3952dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s mismatched signs\n", __FUNCTION__); 3953dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 3954dac1d17027dcaa5596885a9f333979418b35001ccaryclark // return set_last(last, &endSpan); 3955dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3956dac1d17027dcaa5596885a9f333979418b35001ccaryclark other = next->segment(); 3957dac1d17027dcaa5596885a9f333979418b35001ccaryclark foundIndex = end = next->start(); 3958dac1d17027dcaa5596885a9f333979418b35001ccaryclark otherEnd = next->end(); 3959570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 3960dac1d17027dcaa5596885a9f333979418b35001ccaryclark int foundStep = foundIndex < otherEnd ? 1 : -1; 3961dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (*stepPtr != foundStep) { 3962dac1d17027dcaa5596885a9f333979418b35001ccaryclark return set_last(last, &endSpan); 396307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 3964dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkASSERT(*indexPtr >= 0); 396565b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark if (otherEnd < 0) { 396665b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark return NULL; 396765b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark } 396865b427cff9cd34a06ff060d65d00cc3615d8fd94caryclark// SkASSERT(otherEnd >= 0); 3969dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if 1 3970dac1d17027dcaa5596885a9f333979418b35001ccaryclark int origMin = origIndex + (step < 0 ? step : 0); 3971dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& orig = this->span(origMin); 3972dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 3973dac1d17027dcaa5596885a9f333979418b35001ccaryclark int foundMin = SkMin32(foundIndex, otherEnd); 3974dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if 1 3975dac1d17027dcaa5596885a9f333979418b35001ccaryclark const SkOpSpan& found = other->span(foundMin); 3976dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (found.fWindValue != orig.fWindValue || found.fOppValue != orig.fOppValue) { 3977dac1d17027dcaa5596885a9f333979418b35001ccaryclark return set_last(last, &endSpan); 3978dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 3979dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif 3980dac1d17027dcaa5596885a9f333979418b35001ccaryclark *indexPtr = foundIndex; 3981dac1d17027dcaa5596885a9f333979418b35001ccaryclark *stepPtr = foundStep; 3982dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (minPtr) { 3983dac1d17027dcaa5596885a9f333979418b35001ccaryclark *minPtr = foundMin; 3984a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com } 398507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return other; 398607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 398707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 398807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// This has callers for two different situations: one establishes the end 398907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// of the current span, and one establishes the beginning of the next span 399007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// (thus the name). When this is looking for the end of the current span, 399107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// coincidence is found when the beginning Ts contain -step and the end 399207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// contains step. When it is looking for the beginning of the next, the 399307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// first Ts found can be ignored and the last Ts should contain -step. 399407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// OPTIMIZATION: probably should split into two functions 399507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::nextSpan(int from, int step) const { 399607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& fromSpan = fTs[from]; 399707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int count = fTs.count(); 399807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int to = from; 399907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (step > 0 ? ++to < count : --to >= 0) { 400007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com const SkOpSpan& span = fTs[to]; 400107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_zero(span.fT - fromSpan.fT)) { 400207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com continue; 400307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 400407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return to; 400507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 400607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return -1; 400707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 400807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 400907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// FIXME 401007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// this returns at any difference in T, vs. a preset minimum. It may be 401107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// that all callers to nextSpan should use this instead. 401207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::nextExactSpan(int from, int step) const { 401307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int to = from; 4014570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (step < 0) { 4015570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& fromSpan = fTs[from]; 4016570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (--to >= 0) { 4017570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& span = fTs[to]; 4018570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (precisely_negative(fromSpan.fT - span.fT) || span.fTiny) { 4019570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 4020570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4021570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return to; 4022570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4023570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } else { 4024570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (fTs[from].fTiny) { 4025570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com from++; 4026570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4027570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& fromSpan = fTs[from]; 4028570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int count = fTs.count(); 4029570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com while (++to < count) { 4030570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkOpSpan& span = fTs[to]; 4031570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (precisely_negative(span.fT - fromSpan.fT)) { 4032570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com continue; 4033570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4034570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return to; 403507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 403607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 403707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return -1; 403807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 403907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 4040dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::pinT(const SkPoint& pt, double* t) { 4041dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (pt == fPts[0]) { 4042dac1d17027dcaa5596885a9f333979418b35001ccaryclark *t = 0; 4043dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 4044dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = SkPathOpsVerbToPoints(fVerb); 4045dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (pt == fPts[count]) { 4046dac1d17027dcaa5596885a9f333979418b35001ccaryclark *t = 1; 4047dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 4048dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 4049dac1d17027dcaa5596885a9f333979418b35001ccaryclark 40505e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclarkbool SkOpSegment::reversePoints(const SkPoint& p1, const SkPoint& p2) const { 40515e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark SkASSERT(p1 != p2); 40525e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark int spanCount = count(); 40535e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark int p1IndexMin = -1; 40545e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark int p2IndexMax = spanCount; 40555e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark for (int index = 0; index < spanCount; ++index) { 40565e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark const SkOpSpan& span = fTs[index]; 40575e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark if (span.fPt == p1) { 40585e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark if (p1IndexMin < 0) { 40595e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark p1IndexMin = index; 40605e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } 40615e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } else if (span.fPt == p2) { 40625e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark p2IndexMax = index; 40635e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } 40645e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark } 40655e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark return p1IndexMin > p2IndexMax; 40665e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark} 40675e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark 4068dac1d17027dcaa5596885a9f333979418b35001ccaryclarkvoid SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt, 4069dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSegment* other) { 4070dac1d17027dcaa5596885a9f333979418b35001ccaryclark int count = this->count(); 4071dac1d17027dcaa5596885a9f333979418b35001ccaryclark for (int index = 0; index < count; ++index) { 4072dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpSpan &span = fTs[index]; 4073dac1d17027dcaa5596885a9f333979418b35001ccaryclark if ((startPt == span.fPt || endPt == span.fPt) && other == span.fOther) { 4074dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fCoincident = true; 4075dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 4076dac1d17027dcaa5596885a9f333979418b35001ccaryclark } 4077dac1d17027dcaa5596885a9f333979418b35001ccaryclark} 4078dac1d17027dcaa5596885a9f333979418b35001ccaryclark 407907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding, 408007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding) { 408107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int deltaSum = spanSign(index, endIndex); 408207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppDeltaSum = oppSign(index, endIndex); 408307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (operand()) { 408407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumSuWinding; 408507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumSuWinding -= deltaSum; 408607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumMiWinding; 408707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumMiWinding -= oppDeltaSum; 408807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } else { 408907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *maxWinding = *sumMiWinding; 409007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *sumWinding = *sumMiWinding -= deltaSum; 409107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppMaxWinding = *sumSuWinding; 409207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *oppSumWinding = *sumSuWinding -= oppDeltaSum; 409307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 40948cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_LIMIT_WIND_SUM 40958cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 40968cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM); 40978cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 4098570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4099570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4100570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, 4101570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int* maxWinding, int* sumWinding) { 4102570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int deltaSum = spanSign(index, endIndex); 4103570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com *maxWinding = *sumMiWinding; 4104570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com *sumWinding = *sumMiWinding -= deltaSum; 41058cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_LIMIT_WIND_SUM 41068cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM); 41078cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif 410807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 410907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 41104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgvoid SkOpSegment::sortAngles() { 41114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int spanCount = fTs.count(); 41124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (spanCount <= 2) { 41134431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org return; 41144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index = 0; 41164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 4117dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* fromAngle = fTs[index].fFromAngle; 4118dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* toAngle = fTs[index].fToAngle; 4119dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (!fromAngle && !toAngle) { 41204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index += 1; 41214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 41224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpAngle* baseAngle = NULL; 4124dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (fromAngle) { 4125dac1d17027dcaa5596885a9f333979418b35001ccaryclark baseAngle = fromAngle; 41264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (inLoop(baseAngle, spanCount, &index)) { 41274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 41284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 4130cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#if DEBUG_ANGLE 41314431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org bool wroteAfterHeader = false; 4132cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#endif 4133dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (toAngle) { 41344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!baseAngle) { 41354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = toAngle; 41364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (inLoop(baseAngle, spanCount, &index)) { 41374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org continue; 41384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41394431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } else { 41404431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDEBUGCODE(int newIndex = index); 41414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex == index); 41424431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 41434431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT, 41444431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index); 41454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org wroteAfterHeader = true; 41464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 41474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle->insert(toAngle); 414807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 414907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 4150dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* nextFrom, * nextTo; 41514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int firstIndex = index; 41524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 41534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan& span = fTs[index]; 41544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSegment* other = span.fOther; 41554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan& oSpan = other->fTs[span.fOtherIndex]; 4156dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkOpAngle* oAngle = oSpan.fFromAngle; 4157dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oAngle) { 4158570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#if DEBUG_ANGLE 41594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!wroteAfterHeader) { 41604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT, 41614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index); 41624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org wroteAfterHeader = true; 41634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 4164570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com#endif 41658cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (!oAngle->loopContains(*baseAngle)) { 41668cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org baseAngle->insert(oAngle); 41678cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 41684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 4169dac1d17027dcaa5596885a9f333979418b35001ccaryclark oAngle = oSpan.fToAngle; 4170dac1d17027dcaa5596885a9f333979418b35001ccaryclark if (oAngle) { 41714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE 41724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (!wroteAfterHeader) { 41734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT, 41744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index); 41754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org wroteAfterHeader = true; 41764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 41788cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (!oAngle->loopContains(*baseAngle)) { 41798cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org baseAngle->insert(oAngle); 41808cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 41814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 41824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (++index == spanCount) { 41834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 41844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 4185dac1d17027dcaa5596885a9f333979418b35001ccaryclark nextFrom = fTs[index].fFromAngle; 4186dac1d17027dcaa5596885a9f333979418b35001ccaryclark nextTo = fTs[index].fToAngle; 4187dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (fromAngle == nextFrom && toAngle == nextTo); 41884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (baseAngle && baseAngle->loopCount() == 1) { 41894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org index = firstIndex; 41904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org do { 41914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkOpSpan& span = fTs[index]; 4192dac1d17027dcaa5596885a9f333979418b35001ccaryclark span.fFromAngle = span.fToAngle = NULL; 41934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org if (++index == spanCount) { 41944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org break; 41954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 4196dac1d17027dcaa5596885a9f333979418b35001ccaryclark nextFrom = fTs[index].fFromAngle; 4197dac1d17027dcaa5596885a9f333979418b35001ccaryclark nextTo = fTs[index].fToAngle; 4198dac1d17027dcaa5596885a9f333979418b35001ccaryclark } while (fromAngle == nextFrom && toAngle == nextTo); 41994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org baseAngle = NULL; 42004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } 42014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_SORT 42024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org SkASSERT(!baseAngle || baseAngle->loopCount() > 1); 42034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif 42044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org } while (index < spanCount); 4205570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4206570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4207cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed 4208cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.combool SkOpSegment::subDivide(int start, int end, SkPoint edge[4]) const { 4209cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 421007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com edge[0] = fTs[start].fPt; 4211cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 4212cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[points] = fTs[end].fPt; 4213cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 4214cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4215cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4216cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com double startT = fTs[start].fT; 4217cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com double endT = fTs[end].fT; 4218cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 4219cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 422007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 4221cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[1]; 4222cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 422307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 4224cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 4225cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (start < end) { 4226cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[1]; 4227cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = fPts[2]; 4228cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4229cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4230cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = fPts[2]; 4231cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = fPts[1]; 4232cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4233cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4234cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com const SkDPoint sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[points].fX, edge[points].fY }}; 4235cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 4236cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = SkDQuad::SubDivide(fPts, sub[0], sub[1], startT, endT).asSkPoint(); 4237cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 4238cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 4239cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDPoint ctrl[2]; 4240cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDCubic::SubDivide(fPts, sub[0], sub[1], startT, endT, ctrl); 4241cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[1] = ctrl[0].asSkPoint(); 4242cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com edge[2] = ctrl[1].asSkPoint(); 424307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 4244cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 4245cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com} 4246cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com 4247cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com// return true if midpoints were computed 4248cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.combool SkOpSegment::subDivide(int start, int end, SkDCubic* result) const { 4249cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(start != end); 4250cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[0].set(fTs[start].fPt); 4251cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com int points = SkPathOpsVerbToPoints(fVerb); 4252cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[points].set(fTs[end].fPt); 4253cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kLine_Verb) { 4254cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4255cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4256cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com double startT = fTs[start].fT; 4257cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com double endT = fTs[end].fT; 4258cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if ((startT == 0 || endT == 0) && (startT == 1 || endT == 1)) { 4259cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com // don't compute midpoints if we already have them 4260cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 4261cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[1]); 4262cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4263cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4264cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 4265cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (start < end) { 4266cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[1]); 4267cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[2].set(fPts[2]); 4268cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4269cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4270cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1].set(fPts[2]); 4271cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[2].set(fPts[1]); 4272cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return false; 4273cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4274cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com if (fVerb == SkPath::kQuad_Verb) { 4275cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com (*result)[1] = SkDQuad::SubDivide(fPts, (*result)[0], (*result)[2], startT, endT); 4276cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } else { 4277cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkASSERT(fVerb == SkPath::kCubic_Verb); 4278cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com SkDCubic::SubDivide(fPts, (*result)[0], (*result)[3], startT, endT, &(*result)[1]); 4279cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com } 4280cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com return true; 428107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 428207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 428307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const { 428407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkPoint edge[4]; 428507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com subDivide(start, end, edge); 4286277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com (bounds->*SetCurveBounds[SkPathOpsVerbToPoints(fVerb)])(edge); 428707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 428807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 4289570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::TrackOutsidePair(SkTArray<SkPoint, true>* outsidePts, const SkPoint& endPt, 4290570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com const SkPoint& startPt) { 4291570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int outCount = outsidePts->count(); 4292570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (outCount == 0 || endPt != (*outsidePts)[outCount - 2]) { 4293570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com outsidePts->push_back(endPt); 4294570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com outsidePts->push_back(startPt); 4295570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4296570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4297570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4298570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comvoid SkOpSegment::TrackOutside(SkTArray<SkPoint, true>* outsidePts, const SkPoint& startPt) { 4299570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int outCount = outsidePts->count(); 4300570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (outCount == 0 || startPt != (*outsidePts)[outCount - 1]) { 4301570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com outsidePts->push_back(startPt); 430207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 430307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 430407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 430507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::undoneSpan(int* start, int* end) { 43064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int tCount = fTs.count(); 43074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org int index; 430807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com for (index = 0; index < tCount; ++index) { 430907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (!fTs[index].fDone) { 431007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com break; 431107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 431207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 431307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(index < tCount - 1); 431407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *start = index; 431507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com double startT = fTs[index].fT; 431607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com while (approximately_negative(fTs[++index].fT - startT)) 431707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(index < tCount); 431807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(index < tCount); 431907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *end = index; 432007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 432107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 432207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(int index, int endIndex) const { 432307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = SkMin32(index, endIndex); 432407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppWinding = oppSum(lesser); 432507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int oppSpanWinding = oppSign(index, endIndex); 432607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (oppSpanWinding && UseInnerWinding(oppWinding - oppSpanWinding, oppWinding) 432707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com && oppWinding != SK_MaxS32) { 432807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com oppWinding -= oppSpanWinding; 432907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 433007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return oppWinding; 433107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 433207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 433307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWinding(const SkOpAngle* angle) const { 433407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int startIndex = angle->start(); 433507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int endIndex = angle->end(); 433607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return updateOppWinding(endIndex, startIndex); 433707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 433807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 433907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { 434007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int startIndex = angle->start(); 434107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int endIndex = angle->end(); 434207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return updateOppWinding(startIndex, endIndex); 434307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 434407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 434507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWinding(int index, int endIndex) const { 434607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int lesser = SkMin32(index, endIndex); 434707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int winding = windSum(lesser); 43488cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org if (winding == SK_MinS32) { 43498cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org return winding; 43508cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org } 435107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int spanWinding = spanSign(index, endIndex); 4352570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (winding && UseInnerWinding(winding - spanWinding, winding) 4353570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && winding != SK_MaxS32) { 435407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com winding -= spanWinding; 435507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 435607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return winding; 435707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 435807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 435907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWinding(const SkOpAngle* angle) const { 436007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int startIndex = angle->start(); 436107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int endIndex = angle->end(); 436207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return updateWinding(endIndex, startIndex); 436307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 436407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 4365570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comint SkOpSegment::updateWindingReverse(int index, int endIndex) const { 4366570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int lesser = SkMin32(index, endIndex); 4367570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int winding = windSum(lesser); 4368570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int spanWinding = spanSign(endIndex, index); 4369570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com if (winding && UseInnerWindingReverse(winding - spanWinding, winding) 4370570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com && winding != SK_MaxS32) { 4371570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com winding -= spanWinding; 4372570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com } 4373570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return winding; 4374570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4375570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 437607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::updateWindingReverse(const SkOpAngle* angle) const { 437707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int startIndex = angle->start(); 437807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int endIndex = angle->end(); 4379570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return updateWindingReverse(endIndex, startIndex); 4380570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4381570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4382570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// OPTIMIZATION: does the following also work, and is it any faster? 4383570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// return outerWinding * innerWinding > 0 4384570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com// || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0))) 4385570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) { 4386570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(outerWinding != SK_MaxS32); 4387570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(innerWinding != SK_MaxS32); 4388570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absOut = abs(outerWinding); 4389570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absIn = abs(innerWinding); 4390570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; 4391570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return result; 4392570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com} 4393570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com 4394570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.combool SkOpSegment::UseInnerWindingReverse(int outerWinding, int innerWinding) { 4395570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(outerWinding != SK_MaxS32); 4396570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com SkASSERT(innerWinding != SK_MaxS32); 4397570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absOut = abs(outerWinding); 4398570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com int absIn = abs(innerWinding); 4399570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com bool result = absOut == absIn ? true : absOut < absIn; 4400570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com return result; 440107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 440207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 440307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const { 440407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span, disregard 440507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; 440607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 440707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex); 440807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(winding != SK_MinS32); 440907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex); 441007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 4411dac1d17027dcaa5596885a9f333979418b35001ccaryclark SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __FUNCTION__, 4412dac1d17027dcaa5596885a9f333979418b35001ccaryclark debugID(), crossOpp, tHit, t(tIndex), winding, windVal); 441307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 441407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com // see if a + change in T results in a +/- change in X (compute x'(T)) 4415277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com *dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; 441607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { 441707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *dx = fPts[2].fX - fPts[1].fX - *dx; 441807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 441907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (*dx == 0) { 442007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 442107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf(" dx=0 winding=SK_MinS32\n"); 442207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 442307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return SK_MinS32; 442407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 4425a4aced47281e085201a356ce888b92138846e9f6skia.committer@gmail.com if (windVal < 0) { // reverse sign if opp contour traveled in reverse 442607e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com *dx = -*dx; 442707e97fccd2d85076cd22ef411b0773ab92a18abecaryclark@google.com } 442807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com if (winding * *dx > 0) { // if same signs, result is negative 442907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com winding += *dx > 0 ? -windVal : windVal; 443007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com } 443107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING_AT_T 443207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); 443307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif 443407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return winding; 443507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 443607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 443707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comint SkOpSegment::windSum(const SkOpAngle* angle) const { 443807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int start = angle->start(); 443907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int end = angle->end(); 444007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com int index = SkMin32(start, end); 444107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com return windSum(index); 444207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 444307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com 444407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkOpSegment::zeroSpan(SkOpSpan* span) { 4445a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); 444607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fWindValue = 0; 444707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fOppValue = 0; 44487eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com if (span->fTiny || span->fSmall) { 44497eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com return; 44507eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com } 445107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com SkASSERT(!span->fDone); 445207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com span->fDone = true; 445307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com ++fDoneSpans; 445407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com} 4455