ShapeOps.cpp revision 7ba591eb7a7ff71127172bbf140491e18298a97a
1235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com/* 2235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com * Copyright 2012 Google Inc. 3235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com * 4235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com * Use of this source code is governed by a BSD-style license that can be 5235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com * found in the LICENSE file. 6235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com */ 77ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com 8235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#include "Simplify.h" 9235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 10235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.comnamespace Op { 11235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 127ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com#define INCLUDED_BY_SHAPE_OPS 1 137ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com 14235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#include "Simplify.cpp" 15235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 1631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com// FIXME: this and find chase should be merge together, along with 1731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com// other code that walks winding in angles 1831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com// OPTIMIZATION: Probably, the walked winding should be rolled into the angle structure 1931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com// so it isn't duplicated by walkers like this one 2031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.comstatic Segment* findChaseOp(SkTDArray<Span*>& chase, int& tIndex, int& endIndex) { 2131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com while (chase.count()) { 2231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com Span* span; 2331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com chase.pop(&span); 2431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com const Span& backPtr = span->fOther->span(span->fOtherIndex); 2531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com Segment* segment = backPtr.fOther; 2631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com tIndex = backPtr.fOtherIndex; 2731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkTDArray<Angle> angles; 2831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int done = 0; 2931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (segment->activeAngle(tIndex, done, angles)) { 3031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com Angle* last = angles.end() - 1; 3131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com tIndex = last->start(); 3231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com endIndex = last->end(); 3331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if TRY_ROTATE 3431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com *chase.insert(0) = span; 3531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #else 3631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com *chase.append() = span; 3731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 3831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return last->segment(); 3931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 4031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (done == angles.count()) { 4131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com continue; 4231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 4331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkTDArray<Angle*> sorted; 4431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool sortable = Segment::SortAngles(angles, sorted); 4531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com#if DEBUG_SORT 4631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0); 4731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com#endif 4831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!sortable) { 4931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com continue; 5031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 5131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // find first angle, initialize winding to computed fWindSum 5231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int firstIndex = -1; 5331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com const Angle* angle; 5431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int winding; 5531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com do { 5631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com angle = sorted[++firstIndex]; 5731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment = angle->segment(); 5831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com winding = segment->windSum(angle); 5931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } while (winding == SK_MinS32); 6031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int spanWinding = segment->spanSign(angle->start(), angle->end()); 6131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if DEBUG_WINDING 6231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkDebugf("%s winding=%d spanWinding=%d\n", 6331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com __FUNCTION__, winding, spanWinding); 6431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 6531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // turn span winding into contour winding 6631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (spanWinding * winding < 0) { 6731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com winding += spanWinding; 6831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 6931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // we care about first sign and whether wind sum indicates this 7031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // edge is inside or outside. Maybe need to pass span winding 7131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // or first winding or something into this function? 7231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // advance to first undone angle, then return it and winding 7331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com // (to set whether edges are active or not) 7431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int nextIndex = firstIndex + 1; 7531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int angleCount = sorted.count(); 7631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int lastIndex = firstIndex != 0 ? firstIndex : angleCount; 7731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com angle = sorted[firstIndex]; 7831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment = angle->segment(); 7931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int oWinding = segment->oppSum(angle); 8031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if DEBUG_SORT 8131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, oWinding); 8231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 8331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com winding -= segment->spanSign(angle); 8457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oWinding -= segment->oppSign(angle); 8531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool firstOperand = segment->operand(); 8631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com do { 8731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkASSERT(nextIndex != firstIndex); 8831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (nextIndex == angleCount) { 8931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com nextIndex = 0; 9031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 9131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com angle = sorted[nextIndex]; 9231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment = angle->segment(); 9331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int deltaSum = segment->spanSign(angle); 9457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com int deltaOppSum = segment->oppSign(angle); 9531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool angleIsOp = segment->operand() ^ firstOperand; 9631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int maxWinding; 9731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (angleIsOp) { 9831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com maxWinding = oWinding; 9931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com oWinding -= deltaSum; 10057cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com winding -= deltaOppSum; 10131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } else { 10231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com maxWinding = winding; 10331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com winding -= deltaSum; 10457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oWinding -= deltaOppSum; 10531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 10631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if DEBUG_SORT 10731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkDebugf("%s id=%d maxWinding=%d winding=%d oWinding=%d sign=%d\n", __FUNCTION__, 10831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment->debugID(), maxWinding, winding, oWinding, angle->sign()); 10931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 11031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com tIndex = angle->start(); 11131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com endIndex = angle->end(); 11231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int lesser = SkMin32(tIndex, endIndex); 11331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com const Span& nextSpan = segment->span(lesser); 11431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!nextSpan.fDone) { 11531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (angleIsOp) { 11631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkTSwap(winding, oWinding); 11731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 11831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (useInnerWinding(maxWinding, winding)) { 11931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com maxWinding = winding; 12031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 12131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com segment->markWinding(lesser, maxWinding, oWinding); 12231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com break; 12331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 12431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } while (++nextIndex != lastIndex); 12531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if TRY_ROTATE 12631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com *chase.insert(0) = span; 12731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #else 12831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com *chase.append() = span; 12931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 13031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return segment; 13131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 13231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return NULL; 133235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com} 134235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 13557cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.comstatic bool windingIsActive(int winding, int oppWinding, int spanWinding, int oppSpanWinding, 13631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool windingIsOp, ShapeOp op) { 13731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool active = windingIsActive(winding, spanWinding); 13831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!active) { 13931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return false; 14031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 14157cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com if (oppSpanWinding && windingIsActive(oppWinding, oppSpanWinding)) { 14257cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com return op == kIntersect_Op || op == kUnion_Op; 14357cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com } 14431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool opActive = oppWinding != 0; 14531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return gOpLookup[op][opActive][windingIsOp]; 14631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com} 14731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com 14857cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.comstatic int updateWindings(const Segment* current, int index, int endIndex, 14957cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com int& spanWinding, int& oppWinding, int& oppSpanWinding) { 15057cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com int winding = updateWindings(current, index, endIndex, spanWinding); 15157cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com int lesser = SkMin32(index, endIndex); 15257cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oppWinding = current->oppSum(lesser); 15357cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oppSpanWinding = current->oppSign(index, endIndex); 15457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com if (oppSpanWinding && useInnerWinding(oppWinding - oppSpanWinding, oppWinding)) { 15557cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oppWinding -= oppSpanWinding; 15657cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com } 15757cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com return winding; 15857cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com} 15957cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com 16031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.comstatic bool bridgeOp(SkTDArray<Contour*>& contourList, const ShapeOp op, 161f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com const int aXorMask, const int bXorMask, PathWrapper& simple) { 162235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com bool firstContour = true; 16331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool unsortable = false; 16431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com bool closable = true; 165f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; 166235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com do { 167fb51afb03e76c5701fffaa847584a8b7b2c18a7ecaryclark@google.com int index, endIndex; 168f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com Segment* current = findSortableTop(contourList, index, endIndex, topLeft); 169fb51afb03e76c5701fffaa847584a8b7b2c18a7ecaryclark@google.com if (!current) { 170fb51afb03e76c5701fffaa847584a8b7b2c18a7ecaryclark@google.com break; 171fb51afb03e76c5701fffaa847584a8b7b2c18a7ecaryclark@google.com } 17231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int contourWinding, oppContourWinding; 173235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (firstContour) { 17431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com contourWinding = oppContourWinding = 0; 175235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com firstContour = false; 176235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } else { 1776ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com int minIndex = SkMin32(index, endIndex); 1786ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com int sumWinding = current->windSum(minIndex); 1796ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com int oppSumWinding = current->oppSum(minIndex); 180235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // FIXME: don't I have to adjust windSum to get contourWinding? 181235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (sumWinding == SK_MinS32) { 1826ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com sumWinding = current->computeSum(index, endIndex, &oppSumWinding); 183235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 184235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (sumWinding == SK_MinS32) { 185235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com contourWinding = innerContourCheck(contourList, current, 18631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com index, endIndex, false); 18731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com oppContourWinding = innerContourCheck(contourList, current, 18831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com index, endIndex, true); 189235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } else { 1906ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com int spanWinding, oppWinding; 1917ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com contourWinding = updateWindings(current, index, endIndex, spanWinding, 1927ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com oppContourWinding, oppWinding); 193235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#if DEBUG_WINDING 1946ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com SkDebugf("%s contourWinding=%d oppContourWinding=%d spanWinding=%d oppWinding=%d\n", 1956ec1526680bcc05b8b8b2c7ad9f78ba247e123b7caryclark@google.com __FUNCTION__, contourWinding, oppContourWinding, spanWinding, oppWinding); 196235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#endif 197235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 198235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#if DEBUG_WINDING 199235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // SkASSERT(current->debugVerifyWinding(index, endIndex, contourWinding)); 200235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com SkDebugf("%s contourWinding=%d\n", __FUNCTION__, contourWinding); 201235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com#endif 202235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 203235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com int winding = contourWinding; 20431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int oppWinding = oppContourWinding; 205235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com int spanWinding = current->spanSign(index, endIndex); 20657cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com int oppSpanWinding = current->oppSign(index, endIndex); 207235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com SkTDArray<Span*> chaseArray; 208235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com do { 20957cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com bool active = windingIsActive(winding, oppWinding, spanWinding, oppSpanWinding, 21031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current->operand(), op); 211235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com #if DEBUG_WINDING 21257cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com SkDebugf("%s active=%s winding=%d oppWinding=%d spanWinding=%d oppSpanWinding=%d\n", 213235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com __FUNCTION__, active ? "true" : "false", 21457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com winding, oppWinding, spanWinding, oppSpanWinding); 215235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com #endif 216235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com do { 21731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #if DEBUG_ACTIVE_SPANS 21831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!unsortable && current->done()) { 21931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com debugShowActiveSpans(contourList); 22031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 22131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com #endif 22231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkASSERT(unsortable || !current->done()); 223235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com int nextStart = index; 224235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com int nextEnd = endIndex; 225235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Segment* next = current->findNextOp(chaseArray, active, 22657cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com nextStart, nextEnd, winding, oppWinding, spanWinding, oppSpanWinding, 22731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com unsortable, op, aXorMask, bXorMask); 228235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (!next) { 229c91dfe417a51f73c28ecf2708df1e0bee942c6eacaryclark@google.com SkASSERT(!unsortable); 23031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (active && !unsortable && simple.hasMove() 231f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com && current->verb() != SkPath::kLine_Verb 232f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com && !simple.isClosed()) { 23331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current->addCurveTo(index, endIndex, simple, true); 234f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com SkASSERT(simple.isClosed()); 235235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 236235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com break; 237235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 23831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current->addCurveTo(index, endIndex, simple, active); 239235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com current = next; 240235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com index = nextStart; 241235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com endIndex = nextEnd; 24231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } while (!simple.isClosed() 24331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com && ((active && !unsortable) || !current->done())); 24431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (active) { 24531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!simple.isClosed()) { 24631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com SkASSERT(unsortable); 24731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com int min = SkMin32(index, endIndex); 24831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com if (!current->done(min)) { 24931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current->addCurveTo(index, endIndex, simple, true); 25031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current->markDone(SkMin32(index, endIndex), winding ? winding : spanWinding); 25131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 25231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com closable = false; 25331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com } 254235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com simple.close(); 255235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 25631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com current = findChaseOp(chaseArray, index, endIndex); 257235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com #if DEBUG_ACTIVE_SPANS 258235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com debugShowActiveSpans(contourList); 259235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com #endif 260235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (!current) { 261235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com break; 262235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 26357cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com winding = updateWindings(current, index, endIndex, spanWinding, oppWinding, 26457cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com oppSpanWinding); 265235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } while (true); 266235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } while (true); 26731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com return closable; 268235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com} 269235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 270235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com} // end of Op namespace 271235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 272235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com 273235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.comvoid operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result) { 274235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com result.reset(); 275235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com result.setFillType(SkPath::kEvenOdd_FillType); 276235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // turn path into list of segments 277235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com SkTArray<Op::Contour> contours; 278235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // FIXME: add self-intersecting cubics' T values to segment 279235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::EdgeBuilder builder(one, contours); 280235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com const int aXorMask = builder.xorMask(); 281235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com builder.addOperand(two); 282235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com const int bXorMask = builder.xorMask(); 283235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com builder.finish(); 284235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com SkTDArray<Op::Contour*> contourList; 285235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com makeContourList(contours, contourList); 286235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::Contour** currentPtr = contourList.begin(); 287235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com if (!currentPtr) { 288235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com return; 289235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } 290235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::Contour** listEnd = contourList.end(); 291235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // find all intersections between segments 292235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com do { 293235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::Contour** nextPtr = currentPtr; 294235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::Contour* current = *currentPtr++; 295235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com Op::Contour* next; 296235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com do { 297235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com next = *nextPtr++; 298235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } while (addIntersectTs(current, next) && nextPtr != listEnd); 299235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com } while (currentPtr != listEnd); 300235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // eat through coincident edges 3017ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com 3027ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com int total = 0; 3037ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com int index; 3047ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com for (index = 0; index < contourList.count(); ++index) { 3057ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com total += contourList[index]->segments().count(); 3067ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com } 3077ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com#if DEBUG_WINDING 3087ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com Op::Contour::debugShowWindingValues(contourList); 3097ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com#endif 31057cff8dbdfb32b3fea426519a4fdc05f13be69d9caryclark@google.com coincidenceCheck(contourList, (aXorMask == kEvenOdd_Mask) 3117ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com ^ (bXorMask == kEvenOdd_Mask), total); 3127ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com#if DEBUG_WINDING 3137ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com Op::Contour::debugShowWindingValues(contourList); 3147ba591eb7a7ff71127172bbf140491e18298a97acaryclark@google.com#endif 315235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com fixOtherTIndex(contourList); 31631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com sortSegments(contourList); 31731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com#if DEBUG_ACTIVE_SPANS 31831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com debugShowActiveSpans(contourList); 31931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com#endif 320235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com // construct closed contours 321f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com Op::PathWrapper wrapper(result); 322f839c0359c308fd06895d9f73fc12c4f3869e399caryclark@google.com bridgeOp(contourList, op, aXorMask, bXorMask, wrapper); 323235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com} 324