From: caryclark@google.com Date: Mon, 5 Mar 2012 22:01:21 +0000 (+0000) Subject: work in progress X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~16715 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4917f17bf6bd8bff7f4b03717dcb02561cf227c9;p=platform%2Fupstream%2FlibSkiaSharp.git work in progress of note, all edge walker tests succeed at this point git-svn-id: http://skia.googlecode.com/svn/trunk@3330 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/experimental/Intersection/EdgeWalker.cpp b/experimental/Intersection/EdgeWalker.cpp index 2c1e5f5..771e639 100644 --- a/experimental/Intersection/EdgeWalker.cpp +++ b/experimental/Intersection/EdgeWalker.cpp @@ -14,9 +14,9 @@ #include "SkTDArray.h" #include "TSearch.h" -static bool gShowDebugf = true; // FIXME: remove once debugging is complete +static bool gShowDebugf = false; // FIXME: remove once debugging is complete static bool gShowPath = false; -static bool gDebugLessThan = true; +static bool gDebugLessThan = false; static int LineIntersect(const SkPoint a[2], const SkPoint b[2], double aRange[2], double bRange[2]) { @@ -165,9 +165,9 @@ public: if (listIndex >= listCount) { break; } + int closeEdgeIndex = -listIndex - 1; SkPoint firstPt, lastLine[2]; bool doMove = true; - bool closed = false; int edgeIndex; do { SkPoint* ptArray = fEdges[listIndex].fPts; @@ -193,7 +193,6 @@ public: lastLine[0] = *start; lastLine[1] = *end; doMove = false; - closed = false; break; } gap = lastLine[1] != *start; @@ -216,15 +215,6 @@ public: lastLine[0] = *start; } lastLine[1] = *end; - if (firstPt == *end) { - simple.lineTo(end->fX, end->fY); - simple.close(); - if (gShowDebugf) { - SkDebugf("%s close 1 (%g, %g)\n", __FUNCTION__, - end->fX, end->fY); - } - closed = true; - } break; default: // FIXME: add other curve types @@ -237,26 +227,31 @@ public: edgeIndex = fBottoms[listIndex]; fBottoms[listIndex] = 0; } - if (!edgeIndex) { + if (edgeIndex) { + listIndex = abs(edgeIndex) - 1; + if (edgeIndex < 0) { + fTops[listIndex] = 0; + } else { + fBottoms[listIndex] = 0; + } + } + if (edgeIndex == closeEdgeIndex || edgeIndex == 0) { + if (lastLine[1] != firstPt) { + simple.lineTo(lastLine[1].fX, lastLine[1].fY); + } simple.lineTo(firstPt.fX, firstPt.fY); simple.close(); if (gShowDebugf) { - SkDebugf("%s close 2 (%g,%g)\n", __FUNCTION__, - firstPt.fX, firstPt.fY); + SkDebugf("%s close (%g, %g)\n", __FUNCTION__, + firstPt.fX, firstPt.fY); } break; } - listIndex = abs(edgeIndex) - 1; - if (edgeIndex < 0) { - fTops[listIndex] = 0; - } else { - fBottoms[listIndex] = 0; - } // if this and next edge go different directions if (advance > 0 ^ edgeIndex < 0) { advance = -advance; } - } while (edgeIndex && !closed); + } while (edgeIndex); } while (true); } @@ -396,8 +391,15 @@ struct Bounds : public SkRect { } }; -struct Intercepts { +class Intercepts { +public: + Intercepts() + : fTopIntercepts(0) + , fBottomIntercepts(0) { + } SkTDArray fTs; + int fTopIntercepts; + int fBottomIntercepts; }; struct InEdge { @@ -407,13 +409,18 @@ struct InEdge { : fBounds.fTop < rh.fBounds.fTop; } - bool add(double* ts, size_t count, ptrdiff_t verbIndex) { + void add(double* ts, size_t count, ptrdiff_t verbIndex) { // FIXME: in the pathological case where there is a ton of intercepts, binary search? bool foundIntercept = false; Intercepts& intercepts = fIntercepts[verbIndex]; for (size_t index = 0; index < count; ++index) { double t = ts[index]; - if (t <= 0 || t >= 1) { + if (t <= 0) { + fContainsIntercepts |= ++intercepts.fTopIntercepts > 1; + continue; + } + if (t >= 1) { + fContainsIntercepts |= ++intercepts.fBottomIntercepts > 1; continue; } foundIntercept = true; @@ -424,14 +431,15 @@ struct InEdge { if (delta > 0) { *intercepts.fTs.insert(idx2) = t; } - return foundIntercept; + fContainsIntercepts = true; + return; } } if (tCount == 0 || t > intercepts.fTs[tCount - 1]) { *intercepts.fTs.append() = t; } } - return foundIntercept; + fContainsIntercepts |= foundIntercept; } bool cached(const InEdge* edge) { @@ -483,7 +491,7 @@ struct InEdge { // temporary data : move this to a separate struct? SkTDArray fCached; // list of edges already intercepted SkTArray fIntercepts; // one per verb - + // persistent data SkTDArray fPts; SkTDArray fVerbs; @@ -739,8 +747,9 @@ struct ActiveEdge { void calcLeft(SkScalar y) { // OPTIMIZE: put a kDone_Verb at the end of the verb list? - if (done(y)) + if (fDone || fBelow.fY > y) { return; // nothing to do; use last + } calcLeft(); } @@ -772,6 +781,7 @@ struct ActiveEdge { void init(const InEdge* edge) { fWorkEdge.init(edge); initT(); + fBelow.fY = SK_ScalarMin; fDone = false; fYBottom = SK_ScalarMin; } @@ -792,7 +802,7 @@ struct ActiveEdge { // t values, since the same t values could exist intersecting non-coincident // edges. bool isCoincidentWith(const ActiveEdge* edge, SkScalar y) const { - if (fAbove.fX != edge->fAbove.fX || fBelow.fX != edge->fBelow.fX) { + if (fAbove != edge->fAbove || fBelow != edge->fBelow) { return false; } uint8_t verb = fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb(); @@ -803,14 +813,7 @@ struct ActiveEdge { } switch (verb) { case SkPath::kLine_Verb: { - int offset = fDone ? -1 : 1; - int edgeOffset = edge->fDone ? -1 : 1; - const SkPoint* pts = fWorkEdge.fPts; - const SkPoint* edgePts = edge->fWorkEdge.fPts; - return (pts->fX - pts[offset].fX) - * (edgePts->fY - edgePts[edgeOffset].fY) - == (pts->fY - pts[offset].fY) - * (edgePts->fX - edgePts[edgeOffset].fX); + return true; } default: // FIXME: add support for all curve types @@ -886,7 +889,12 @@ static void addToActive(SkTDArray& activeEdges, const InEdge* edge) active->init(edge); } - // find any intersections in the range of active edges +// Find any intersections in the range of active edges. A pair of edges, on +// either side of another edge, may change the winding contribution for part of +// the edge. +// OPTIMIZATION: Another approach would be to keep horizontal edges just for +// the purpose of computing when edges change their winding contribution, since +// this is essentially computing the horizontal intersection. static void addBottomT(InEdge** currentPtr, InEdge** lastPtr, SkScalar bottom) { InEdge** testPtr = currentPtr; InEdge* test = *testPtr; @@ -901,8 +909,7 @@ static void addBottomT(InEdge** currentPtr, InEdge** lastPtr, SkScalar bottom) { double wtTs[2]; int pts = LineIntersect(wt.fPts, bottom, wtTs); if (pts) { - test->fContainsIntercepts |= test->add(wtTs, pts, - wt.verbIndex()); + test->add(wtTs, pts, wt.verbIndex()); } } else { // FIXME: add all curve types @@ -936,10 +943,8 @@ static void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) { double wtTs[2], wnTs[2]; int pts = LineIntersect(wt.fPts, wn.fPts, wtTs, wnTs); if (pts) { - test->fContainsIntercepts |= test->add(wtTs, pts, - wt.verbIndex()); - next->fContainsIntercepts |= next->add(wnTs, pts, - wn.verbIndex()); + test->add(wtTs, pts, wt.verbIndex()); + next->add(wnTs, pts, wn.verbIndex()); } } else { // FIXME: add all combinations of curve types @@ -987,6 +992,18 @@ static void computeInterceptBottom(SkTDArray& activeEdges, wt.init(test); do { const Intercepts& intercepts = test->fIntercepts[wt.verbIndex()]; + if (intercepts.fTopIntercepts > 1) { + SkScalar yTop = wt.fPts[0].fY; + if (yTop > y && bottom > yTop) { + bottom = yTop; + } + } + if (intercepts.fBottomIntercepts > 1) { + SkScalar yBottom = wt.fPts[wt.verb()].fY; + if (yBottom > y && bottom > yBottom) { + bottom = yBottom; + } + } const SkTDArray& fTs = intercepts.fTs; size_t count = fTs.count(); for (size_t index = 0; index < count; ++index) { @@ -1099,8 +1116,10 @@ static void sortHorizontal(SkTDArray& activeEdges, // and not all at once as is done here, fold this test into the // current less than test. if (activePtr->swapCoincident(nextPtr, bottom)) { + winding -= activePtr->fWorkEdge.winding(); SkTSwap(edgeList[index - 1], edgeList[index]); SkTSwap(activePtr, nextPtr); + winding += activePtr->fWorkEdge.winding(); } if (!firstCoincident) { firstCoincident = activePtr; @@ -1154,7 +1173,8 @@ static void stitchEdge(SkTDArray& edgeList, SkScalar y, bool closer = (winding & windingMask) == 0; SkASSERT(!opener | !closer); bool inWinding = opener | closer; - const SkPoint* clipped; + SkPoint clippedPts[2]; + const SkPoint* clipped = NULL; uint8_t verb = wt.verb(); bool moreToDo, aboveBottom; do { @@ -1165,7 +1185,6 @@ static void stitchEdge(SkTDArray& edgeList, SkScalar y, do { nextT = activePtr->nextT(); if (verb == SkPath::kLine_Verb) { - SkPoint clippedPts[2]; // FIXME: obtuse: want efficient way to say // !currentT && currentT != 1 || !nextT && nextT != 1 if (currentT * nextT != 0 || currentT + nextT != 1) { @@ -1184,6 +1203,11 @@ static void stitchEdge(SkTDArray& edgeList, SkScalar y, } outBuilder.addLine(clipped); } + if (clipped[1].fY > activePtr->fBelow.fY + && bottom >= activePtr->fBelow.fY ) { + activePtr->fAbove = activePtr->fBelow; + activePtr->fBelow = clipped[1]; + } activePtr->fSkip = false; } else { // FIXME: add all curve types @@ -1214,6 +1238,9 @@ void simplify(const SkPath& path, bool asFill, SkPath& simple) { InEdge edgeSentinel; makeEdgeList(edges, edgeSentinel, edgeList); InEdge** currentPtr = edgeList.begin(); + if (!currentPtr) { + return; + } // walk the sorted edges from top to bottom, computing accumulated winding SkTDArray activeEdges; OutEdgeBuilder outBuilder(asFill); diff --git a/experimental/Intersection/EdgeWalkerPolygons_Test.cpp b/experimental/Intersection/EdgeWalkerPolygons_Test.cpp index 3ea0e0b..07ce6c8 100644 --- a/experimental/Intersection/EdgeWalkerPolygons_Test.cpp +++ b/experimental/Intersection/EdgeWalkerPolygons_Test.cpp @@ -245,6 +245,91 @@ static void testSimplifyTriangle17() { comparePaths(path, out); } +static void testSimplifyTriangle18() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(0, 1); + path.lineTo(1, 2); + path.close(); + path.moveTo(1, 0); + path.lineTo(0, 1); + path.lineTo(0, 3); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplifyTriangle19() { + SkPath path, out; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(0, 0); + path.lineTo(0, 1); + path.lineTo(3, 2); + path.close(); + path.moveTo(0, 0); + path.lineTo(1, 1); + path.lineTo(2, 1); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplifyTriangle20() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(2, 1); + path.lineTo(1, 3); + path.close(); + path.moveTo(2, 0); + path.lineTo(3, 2); + path.lineTo(0, 3); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplifyTriangle21() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(1, 0); + path.lineTo(1, 2); + path.close(); + path.moveTo(2, 0); + path.lineTo(2, 1); + path.lineTo(0, 3); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplifyDegenerateTriangle1() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(0, 0); + path.lineTo(0, 0); + path.close(); + path.moveTo(0, 0); + path.lineTo(0, 0); + path.lineTo(0, 0); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplifyDegenerateTriangle2() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(1, 1); + path.lineTo(2, 2); + path.close(); + path.moveTo(1, 0); + path.lineTo(2, 2); + path.lineTo(3, 3); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + static void testSimplifyWindingParallelogram() { SkPath path, out; path.setFillType(SkPath::kWinding_FillType); @@ -361,6 +446,67 @@ static void testSimplifyNondegenerate4x4Triangles() { } } +static void testSimplifyDegenerate4x4Triangles() { + char pathStr[1024]; + bzero(pathStr, sizeof(pathStr)); + for (int a = 0; a < 16; ++a) { + int ax = a & 0x03; + int ay = a >> 2; + for (int b = a ; b < 16; ++b) { + int bx = b & 0x03; + int by = b >> 2; + for (int c = a ; c < 16; ++c) { + int cx = c & 0x03; + int cy = c >> 2; + bool abcIsATriangle = (bx - ax) * (cy - ay) + != (by - ay) * (cx - ax); + for (int d = 0; d < 16; ++d) { + int dx = d & 0x03; + int dy = d >> 2; + for (int e = d ; e < 16; ++e) { + int ex = e & 0x03; + int ey = e >> 2; + for (int f = d ; f < 16; ++f) { + int fx = f & 0x03; + int fy = f >> 2; + if (abcIsATriangle && (ex - dx) * (fy - dy) + != (ey - dy) * (fx - dx)) { + continue; + } + SkPath path, out; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(ax, ay); + path.lineTo(bx, by); + path.lineTo(cx, cy); + path.close(); + path.moveTo(dx, dy); + path.lineTo(ex, ey); + path.lineTo(fx, fy); + path.close(); + if (1) { + char* str = pathStr; + str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay); + str += sprintf(str, " path.lineTo(%d, %d);\n", bx, by); + str += sprintf(str, " path.lineTo(%d, %d);\n", cx, cy); + str += sprintf(str, " path.close();\n"); + str += sprintf(str, " path.moveTo(%d, %d);\n", dx, dy); + str += sprintf(str, " path.lineTo(%d, %d);\n", ex, ey); + str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy); + str += sprintf(str, " path.close();"); + } + simplify(path, true, out); + comparePaths(path, out); + path.setFillType(SkPath::kEvenOdd_FillType); + simplify(path, true, out); + comparePaths(path, out); + } + } + } + } + } + } +} + static void testPathTriangleRendering() { SkPath one, two; one.moveTo(0, 0); @@ -382,6 +528,12 @@ static void testPathTriangleRendering() { } static void (*simplifyTests[])() = { + testSimplifyDegenerateTriangle2, + testSimplifyDegenerateTriangle1, + testSimplifyTriangle21, + testSimplifyTriangle20, + testSimplifyTriangle19, + testSimplifyTriangle18, testSimplifyTriangle17, testSimplifyTriangle16, testSimplifyTriangle15, @@ -401,6 +553,7 @@ static void (*simplifyTests[])() = { testSimplifyTriangle2, testSimplifyWindingParallelogram, testSimplifyXorParallelogram, + testSimplifyDegenerate4x4Triangles, testSimplifyNondegenerate4x4Triangles, testPathTriangleRendering, }; diff --git a/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp b/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp new file mode 100644 index 0000000..b22e1a3 --- /dev/null +++ b/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp @@ -0,0 +1,108 @@ +#include "EdgeWalker_Test.h" +#include "Intersection_Tests.h" + +static void testSimplifyQuad1() { + SkPath path, out; + path.moveTo(0, 0); + path.lineTo(1, 0); + path.lineTo(3, 2); + path.lineTo(3, 3); + path.close(); + path.moveTo(1, 0); + path.lineTo(1, 3); + path.lineTo(1, 3); + path.lineTo(1, 3); + path.close(); + simplify(path, true, out); + comparePaths(path, out); +} + +static void testSimplify4x4Quadralaterals() { + char pathStr[1024]; + bzero(pathStr, sizeof(pathStr)); + for (int a = 0; a < 16; ++a) { + int ax = a & 0x03; + int ay = a >> 2; + for (int b = a ; b < 16; ++b) { + int bx = b & 0x03; + int by = b >> 2; + for (int c = b ; c < 16; ++c) { + int cx = c & 0x03; + int cy = c >> 2; + for (int d = c; d < 16; ++d) { + int dx = d & 0x03; + int dy = d >> 2; + for (int e = 0 ; e < 16; ++e) { + int ex = e & 0x03; + int ey = e >> 2; + for (int f = e ; f < 16; ++f) { + int fx = f & 0x03; + int fy = f >> 2; + for (int g = f ; g < 16; ++g) { + int gx = g & 0x03; + int gy = g >> 2; + for (int h = g ; g < 16; ++g) { + int hx = h & 0x03; + int hy = h >> 2; + SkPath path, out; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(ax, ay); + path.lineTo(bx, by); + path.lineTo(cx, cy); + path.lineTo(dx, dy); + path.close(); + path.moveTo(ex, ey); + path.lineTo(fx, fy); + path.lineTo(gx, gy); + path.lineTo(hx, hy); + path.close(); + if (1) { + char* str = pathStr; + str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay); + str += sprintf(str, " path.lineTo(%d, %d);\n", bx, by); + str += sprintf(str, " path.lineTo(%d, %d);\n", cx, cy); + str += sprintf(str, " path.lineTo(%d, %d);\n", dx, dy); + str += sprintf(str, " path.close();\n"); + str += sprintf(str, " path.moveTo(%d, %d);\n", ex, ey); + str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy); + str += sprintf(str, " path.lineTo(%d, %d);\n", gx, gy); + str += sprintf(str, " path.lineTo(%d, %d);\n", hx, hy); + str += sprintf(str, " path.close();"); + } + simplify(path, true, out); + comparePaths(path, out); + path.setFillType(SkPath::kEvenOdd_FillType); + simplify(path, true, out); + comparePaths(path, out); + } + } + } + } + } + } + } + } +} + + + +static void (*simplifyTests[])() = { + testSimplifyQuad1, + testSimplify4x4Quadralaterals, +}; + +static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]); + +static void (*firstTest)() = 0; + +void SimplifyQuadralateralPaths_Test() { + size_t index = 0; + if (firstTest) { + while (index < simplifyTestsCount && simplifyTests[index] != firstTest) { + ++index; + } + } + for ( ; index < simplifyTestsCount; ++index) { + (*simplifyTests[index])(); + } +} diff --git a/experimental/Intersection/Intersection_Tests.cpp b/experimental/Intersection/Intersection_Tests.cpp index 42f4a26..2a1620e 100644 --- a/experimental/Intersection/Intersection_Tests.cpp +++ b/experimental/Intersection/Intersection_Tests.cpp @@ -17,8 +17,9 @@ void Intersection_Tests() { LineQuadraticIntersection_Test(); LineCubicIntersection_Test(); - SimplifyPolygonPaths_Test(); SimplifyRectangularPaths_Test(); + SimplifyPolygonPaths_Test(); + SimplifyQuadralateralPaths_Test(); QuadraticCoincidence_Test(); QuadraticReduceOrder_Test(); diff --git a/experimental/Intersection/Intersection_Tests.h b/experimental/Intersection/Intersection_Tests.h index 9def8b5..f007dda 100644 --- a/experimental/Intersection/Intersection_Tests.h +++ b/experimental/Intersection/Intersection_Tests.h @@ -12,6 +12,7 @@ void LineIntersection_Test(); void LineParameter_Test(); void LineQuadraticIntersection_Test(); void SimplifyPolygonPaths_Test(); +void SimplifyQuadralateralPaths_Test(); void SimplifyRectangularPaths_Test(); void QuadraticBezierClip_Test(); void QuadraticCoincidence_Test(); diff --git a/experimental/Intersection/LineIntersection.cpp b/experimental/Intersection/LineIntersection.cpp index 99b9e82..4d80606 100644 --- a/experimental/Intersection/LineIntersection.cpp +++ b/experimental/Intersection/LineIntersection.cpp @@ -59,7 +59,7 @@ int intersect(const _Line& a, const _Line& b, double aRange[2], double bRange[2] bRange[0] = aMin <= bMin ? 0 : (aMin - bMin) / (bMax - bMin); bRange[1] = aMax >= bMax ? 1 : (aMax - bMin) / (bMax - bMin); } - return 2; + return 1 + ((aRange[0] != aRange[1]) || (bRange[0] != bRange[1])); } } double ab0y = a[0].y - b[0].y; diff --git a/experimental/Intersection/edge.xcodeproj/project.pbxproj b/experimental/Intersection/edge.xcodeproj/project.pbxproj index 6180ae8..cf433c6 100644 --- a/experimental/Intersection/edge.xcodeproj/project.pbxproj +++ b/experimental/Intersection/edge.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ FECAA6C714BDCE9B00B35E2C /* QuadraticIntersection_Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FECAA6C614BDCE9B00B35E2C /* QuadraticIntersection_Test.cpp */; }; FECAA6E114BDDF2D00B35E2C /* QuadraticReduceOrder_Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FECAA6E014BDDF2D00B35E2C /* QuadraticReduceOrder_Test.cpp */; }; FED53C391483CB9400F6359E /* Inline_Tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED53C381483CB9400F6359E /* Inline_Tests.cpp */; }; + FED865F915056A79006F4508 /* EdgeWalkerQuadralaterals_Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED865F815056A79006F4508 /* EdgeWalkerQuadralaterals_Test.cpp */; }; FEED7245144DD2250059E97B /* SkEventNotifier.mm in Sources */ = {isa = PBXBuildFile; fileRef = FEED723E144DD2250059E97B /* SkEventNotifier.mm */; }; FEED7292144DD4610059E97B /* libexperimental.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FEED726E144DD4050059E97B /* libexperimental.a */; }; FEED7293144DD4620059E97B /* libskgr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FEED7276144DD4140059E97B /* libskgr.a */; }; @@ -299,6 +300,7 @@ FECAAB7F14BDFAFD00B35E2C /* CubicParameterization_TestUtility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CubicParameterization_TestUtility.cpp; sourceTree = ""; }; FECAACA614BE1C6100B35E2C /* QuadraticParameterization_TestUtility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QuadraticParameterization_TestUtility.cpp; sourceTree = ""; }; FED53C381483CB9400F6359E /* Inline_Tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Inline_Tests.cpp; sourceTree = ""; }; + FED865F815056A79006F4508 /* EdgeWalkerQuadralaterals_Test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeWalkerQuadralaterals_Test.cpp; sourceTree = ""; }; FEED723C144DD2250059E97B /* SampleApp.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = SampleApp.xib; path = ../../src/utils/mac/SampleApp.xib; sourceTree = SOURCE_ROOT; }; FEED723D144DD2250059E97B /* SampleAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SampleAppDelegate.mm; path = ../../src/utils/mac/SampleAppDelegate.mm; sourceTree = SOURCE_ROOT; }; FEED723E144DD2250059E97B /* SkEventNotifier.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SkEventNotifier.mm; path = ../../src/utils/mac/SkEventNotifier.mm; sourceTree = SOURCE_ROOT; }; @@ -536,6 +538,7 @@ FEED7673144F2D770059E97B /* TestUtilities.h */, FEED764B144F29BD0059E97B /* TestUtilities.cpp */, FE7413DB14F6926D00056D7B /* EdgeWalker_Test.h */, + FED865F815056A79006F4508 /* EdgeWalkerQuadralaterals_Test.cpp */, ); name = Tests; sourceTree = ""; @@ -948,6 +951,7 @@ FEA61B2C14F2AF6600B736CB /* EdgeWalkerRectangles_Test.cpp in Sources */, FE7413D414F6915A00056D7B /* EdgeWalkerPolygons_Test.cpp in Sources */, FE7413D814F691C200056D7B /* EdgeWalker_TestUtility.cpp in Sources */, + FED865F915056A79006F4508 /* EdgeWalkerQuadralaterals_Test.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };