11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
8da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#include "Test.h"
9da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#include "../../src/core/SkConcaveToTriangles.h"
10da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#include "SkGeometry.h"
11da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
12da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic int GetIndexFromPoint(const SkPoint &pt,
13da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                             int numPts, const SkPoint *pts) {
14da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    for (int i = 0; i < numPts; ++i)
15da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        if (pt.fX == pts[i].fX && pt.fY == pts[i].fY)
16da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            return i;
17da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    return -1;
18da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
19da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
20da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
21da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedbool gPrintTriangles = false;   // Can we set this on the command line?
22da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
23da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void PrintTriangles(const SkTDArray<SkPoint> &triangles,
24da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                           int numPts, const SkPoint *pts,
25da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                           skiatest::Reporter* reporter) {
26da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    if (gPrintTriangles) {
27da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        SkPoint *p = triangles.begin();
28da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        int n = triangles.count();
29da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        REPORTER_ASSERT(reporter, n % 3 == 0);
30da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        n /= 3;
31da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        printf("%d Triangles:\n{\n", n);
32da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        for (; n-- != 0; p += 3)
33da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            printf("    { {%.7g, %.7g}, {%.7g, %.7g}, {%.7g, %.7g} },  "
34da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                   "// { %2d, %2d, %2d }\n",
35da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                p[0].fX, p[0].fY,
36da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                p[1].fX, p[1].fY,
37da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                p[2].fX, p[2].fY,
38da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                GetIndexFromPoint(p[0], numPts, pts),
39da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                GetIndexFromPoint(p[1], numPts, pts),
40da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                GetIndexFromPoint(p[2], numPts, pts));
41da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        printf("}\n");
42da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    }
43da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
44da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
45da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
46da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic bool CompareTriangleList(int numTriangles,
47da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                const float refTriangles[][3][2],
48da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                const SkTDArray<SkPoint> &triangles) {
49da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    if (triangles.count() != numTriangles * 3) {
50da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        printf("Expected %d triangles, not %d\n",
51da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed               numTriangles, triangles.count() / 3);
52da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        return false;
53da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    }
54da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    int numErrors = 0;
55da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    for (int i = 0; i < numTriangles; ++i) {
56da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        const float *r = &refTriangles[i][0][0];
57da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        const SkScalar *t = &triangles[i * 3].fX;
58da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        bool equalTriangle = true;
59da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        for (int j = 6; j-- != 0; r++, t++)
60da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            if (SkFloatToScalar(*r) != *t)
61da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                equalTriangle = false;
62da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        if (equalTriangle == false) {
63da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            ++numErrors;
64da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            printf("Triangle %d differs\n", i);
65da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        }
66da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    }
67da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    if (numErrors > 0)
68da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        printf("%d triangles differ\n", numErrors);
69da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    return numErrors == 0;
70da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
71da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
72da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
73da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#ifndef LEFT_HANDED_POLYGONS
74da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic const SkPoint star[] = {
75da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    // Outer contour is clockwise if Y is down, counterclockwise if Y is up.
76da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 20)  },
77da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(100), SkFloatToScalar( 50)  },
78da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(130), SkFloatToScalar( 80)  },
79da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 90), SkFloatToScalar( 80)  },
80da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar(120)  },
81da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 80)  },
82da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 80)  },
83da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 40), SkFloatToScalar( 50)  },
84da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 30), SkFloatToScalar( 20)  },
85da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 40)  },
86da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    // Inner contour is counterclockwise if Y is down, clockwise if Y is up.
87da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 20)  },
88da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  },
89da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 60)  },
90da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 70)  },
91da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 70)  },
92da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 60)  },
93da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  }
94da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed};
95da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic const SkPoint plus[] = {
96da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 10)  },
97da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  },
98da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 50)  },
99da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 70)  },
100da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 70)  },
101da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar(110)  },
102da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar(110)  },
103da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 70)  },
104da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 70)  },
105da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 50)  },
106da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 50)  },
107da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 10)  }
108da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed};
109da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic const SkPoint zipper[] = {
110da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 60)  },
111da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 10)  },
112da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 20), SkFloatToScalar( 10)  },
113da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 20), SkFloatToScalar( 50)  },
114da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 30), SkFloatToScalar( 50)  },
115da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 30), SkFloatToScalar( 10)  },
116da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 10)  },
117da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 50)  },
118da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  },
119da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 10)  },
120da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(100), SkFloatToScalar( 10)  },
121da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(100), SkFloatToScalar( 50)  },
122da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 50)  },
123da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 10)  },
124da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(140), SkFloatToScalar( 10)  },
125da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(140), SkFloatToScalar( 60)  },
126da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(130), SkFloatToScalar( 60)  },
127da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(130), SkFloatToScalar( 20)  },
128da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(120), SkFloatToScalar( 20)  },
129da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(120), SkFloatToScalar( 60)  },
130da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 90), SkFloatToScalar( 60)  },
131da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 90), SkFloatToScalar( 20)  },
132da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 20)  },
133da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 60)  },
134da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 60)  },
135da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 20)  },
136da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 40), SkFloatToScalar( 20)  },
137da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 40), SkFloatToScalar( 60)  }
138da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed};
139da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#else  // LEFT_HANDED_POLYGONS
140da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic const SkPoint star[] = {
141da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    // Outer contour is counterclockwise if Y is down, clockwise if Y is up.
142da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 20)  },
143da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 40)  },
144da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 30), SkFloatToScalar( 20)  },
145da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 40), SkFloatToScalar( 50)  },
146da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 10), SkFloatToScalar( 80)  },
147da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 50), SkFloatToScalar( 80)  },
148da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar(120)  },
149da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 90), SkFloatToScalar( 80)  },
150da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(130), SkFloatToScalar( 80)  },
151da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(100), SkFloatToScalar( 50)  },
152da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    // Inner contour is clockwise if Y is down, counterclockwise if Y is up.
153da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar(110), SkFloatToScalar( 20)  },
154da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  },
155da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 60)  },
156da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 80), SkFloatToScalar( 70)  },
157da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 70)  },
158da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 60), SkFloatToScalar( 60)  },
159da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    { SkFloatToScalar( 70), SkFloatToScalar( 50)  }
160da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed};
161da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#endif  // LEFT_HANDED_POLYGONS
162da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#define kNumStarVertices 10
163da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#define kNumStarHoleVertices (sizeof(star) / sizeof(star[0]))
164da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
165da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
166da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed// Star test
167da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void TestStarTriangulation(skiatest::Reporter* reporter) {
168da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    static const float refTriangles[][3][2] = {
169da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 30,  20}, { 70,  40}, { 40,  50} },  // { 8, 9, 7 }
170da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100,  50}, { 10,  80}, { 40,  50} },  // { 1, 6, 7 }
171da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100,  50}, { 40,  50}, { 70,  40} },  // { 1, 7, 9 }
172da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100,  50}, { 70,  40}, {110,  20} },  // { 1, 9, 0 }
173da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 90,  80}, { 70, 120}, { 50,  80} },  // { 3, 4, 5 }
174da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 90,  80}, { 50,  80} },  // { 2, 3, 5 } degen
175da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 50,  80}, { 10,  80} },  // { 2, 5, 6 } degen
176da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 10,  80}, {100,  50} }   // { 2, 6, 1 }
177da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    };
178da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numRefTriangles = sizeof(refTriangles)
179da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                 / (6 * sizeof(refTriangles[0][0][0]));
180da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    SkTDArray<SkPoint> triangles;
181da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    bool success = SkConcaveToTriangles(kNumStarVertices, star, &triangles);
182da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    PrintTriangles(triangles, kNumStarVertices, star, reporter);
183da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    success = CompareTriangleList(numRefTriangles, refTriangles, triangles)
184da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            && success;
185da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    reporter->report("Triangulate Star", success ? reporter->kPassed
186da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                                 : reporter->kFailed);
187da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
188da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
189da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
190da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed// Star with hole test
191da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void TestStarHoleTriangulation(skiatest::Reporter* reporter) {
192da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    static const float refTriangles[][3][2] = {
193da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100,  50}, { 80,  60}, { 70,  50} },  // {  1, 15, 16 }
194da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100,  50}, { 70,  50}, {110,  20} },  // {  1, 16,  0 }
195da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 30,  20}, { 70,  40}, { 40,  50} },  // {  8,  9,  7 }
196da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 60,  70}, { 80,  70}, { 10,  80} },  // { 13, 14,  6 }
197da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 60,  60}, { 60,  70}, { 10,  80} },  // { 12, 13,  6 }
198da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 60,  60}, { 10,  80} },  // { 11, 12,  6 }
199da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 10,  80}, { 40,  50} },  // { 11,  6,  7 }
200da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 40,  50}, { 70,  40} },  // { 11,  7,  9 }
201da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 70,  40}, {110,  20} },  // { 11,  9, 10 }
202da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 90,  80}, { 70, 120}, { 50,  80} },  // {  3,  4,  5 }
203da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 90,  80}, { 50,  80} },  // {  2,  3,  5 } degen
204da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 50,  80}, { 10,  80} },  // {  2,  5,  6 } degen
205da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 10,  80}, { 80,  70} },  // {  2,  6, 14 }
206da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 80,  70}, { 80,  60} },  // {  2, 14, 15 }
207da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130,  80}, { 80,  60}, {100,  50} }   // {  2, 15,  1 }
208da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    };
209da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numRefTriangles = sizeof(refTriangles)
210da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                 / (6 * sizeof(refTriangles[0][0][0]));
211da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    SkTDArray<SkPoint> triangles;
212da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    bool success = SkConcaveToTriangles(kNumStarHoleVertices, star, &triangles);
213da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    PrintTriangles(triangles, kNumStarHoleVertices, star, reporter);
214da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    success = CompareTriangleList(numRefTriangles, refTriangles, triangles)
215da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            && success;
216da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    reporter->report("Triangulate Star With Hole", success ? reporter->kPassed
217da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                                           : reporter->kFailed);
218da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
219da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
220da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
221da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed// Plus test
222da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void TestPlusTriangulation(skiatest::Reporter* reporter) {
223da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    static const float refTriangles[][3][2] = {
224da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 50,  10}, { 70,  10}, { 50, 50} },  // { 11,  0, 10 }
225da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, {110,  50}, { 10, 70} },  // {  1,  2,  8 }
226da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 10,  70}, { 10, 50} },  // {  1,  8,  9 }
227da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 10,  50}, { 50, 50} },  // {  1,  9, 10 }
228da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  50}, { 50,  50}, { 70, 10} },  // {  1, 10,  0 }
229da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70,  70}, { 50, 110}, { 50, 70} },  // {  4,  6,  7 }
230da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {110,  70}, { 70,  70}, { 50, 70} },  // {  3,  4,  7 }
231da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {110,  70}, { 50,  70}, { 10, 70} },  // {  3,  7,  8 }
232da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {110,  70}, { 10,  70}, {110, 50} },  // {  3,  8,  2 }
233da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70, 110}, { 50, 110}, { 70, 70} },  // {  5,  6,  4 }
234da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    };
235da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numRefTriangles = sizeof(refTriangles)
236da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                 / (6 * sizeof(refTriangles[0][0][0]));
237da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    SkTDArray<SkPoint> triangles;
238da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numVertices = sizeof(plus) / sizeof(SkPoint);
239da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    bool success = SkConcaveToTriangles(numVertices, plus, &triangles);
240da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    PrintTriangles(triangles, numVertices, plus, reporter);
241da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    success = CompareTriangleList(numRefTriangles, refTriangles, triangles)
242da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            && success;
243da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    reporter->report("Triangulate Plus", success ? reporter->kPassed
244da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                                 : reporter->kFailed);
245da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
246da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
247da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
248da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed// Zipper test
249da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void TestZipperTriangulation(skiatest::Reporter* reporter) {
250da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    static const float refTriangles[][3][2] = {
251da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 10, 10}, { 20, 10}, { 20, 50} },  // {  1,  2,  3 }
252da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 20, 50}, { 30, 50}, { 10, 60} },  // {  3,  4,  0 }
253da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 10, 10}, { 20, 50}, { 10, 60} },  // {  1,  3,  0 }
254da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 30, 10}, { 60, 10}, { 40, 20} },  // {  5,  6, 26 }
255da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 30, 10}, { 40, 20}, { 30, 50} },  // {  5, 26,  4 }
256da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 40, 60}, { 10, 60}, { 30, 50} },  // { 27,  0,  4 }
257da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 40, 60}, { 30, 50}, { 40, 20} },  // { 27,  4, 26 }
258da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 60, 50}, { 70, 50}, { 50, 60} },  // {  7,  8, 24 }
259da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 50, 20}, { 60, 50}, { 50, 60} },  // { 25,  7, 24 }
260da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 50, 20}, { 40, 20}, { 60, 10} },  // { 25, 26,  6 }
261da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 60, 50}, { 50, 20}, { 60, 10} },  // {  7, 25,  6 }
262da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70, 10}, {100, 10}, { 80, 20} },  // {  9, 10, 22 }
263da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 70, 10}, { 80, 20}, { 70, 50} },  // {  9, 22,  8 }
264da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 80, 60}, { 50, 60}, { 70, 50} },  // { 23, 24,  8 }
265da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 80, 60}, { 70, 50}, { 80, 20} },  // { 23,  8, 22 }
266da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100, 50}, {110, 50}, { 90, 60} },  // { 11, 12, 20 }
267da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 90, 20}, {100, 50}, { 90, 60} },  // { 21, 11, 20 }
268da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { { 90, 20}, { 80, 20}, {100, 10} },  // { 21, 22, 10 }
269da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {100, 50}, { 90, 20}, {100, 10} },  // { 11, 21, 10 }
270da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {110, 10}, {140, 10}, {120, 20} },  // { 13, 14, 18 }
271da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {110, 10}, {120, 20}, {110, 50} },  // { 13, 18, 12 }
272da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {120, 60}, { 90, 60}, {110, 50} },  // { 19, 20, 12 }
273da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {120, 60}, {110, 50}, {120, 20} },  // { 19, 12, 18 }
274da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {140, 60}, {130, 60}, {130, 20} },  // { 15, 16, 17 }
275da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {130, 20}, {120, 20}, {140, 10} },  // { 17, 18, 14 }
276da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed        { {140, 60}, {130, 20}, {140, 10} },  // { 15, 17, 14 }
277da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    };
278da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numRefTriangles = sizeof(refTriangles)
279da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                 / (6 * sizeof(refTriangles[0][0][0]));
280da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    SkTDArray<SkPoint> triangles;
281da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    const size_t numVertices = sizeof(zipper) / sizeof(SkPoint);
282da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    bool success = SkConcaveToTriangles(numVertices, zipper, &triangles);
283da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    PrintTriangles(triangles, numVertices, zipper, reporter);
284da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    success = CompareTriangleList(numRefTriangles, refTriangles, triangles)
285da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed            && success;
286da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    reporter->report("Triangulate Zipper", success ? reporter->kPassed
287da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed                                                   : reporter->kFailed);
288da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
289da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
290da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
291da3b8b285a5e3e6f344461d67e3370b27701756dMike Reedstatic void TestTriangulation(skiatest::Reporter* reporter) {
292da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    TestStarTriangulation(reporter);
293da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    TestStarHoleTriangulation(reporter);
294da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    TestPlusTriangulation(reporter);
295da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed    TestZipperTriangulation(reporter);
296da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed}
297da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed
298da3b8b285a5e3e6f344461d67e3370b27701756dMike Reed#include "TestClassDef.h"
299da3b8b285a5e3e6f344461d67e3370b27701756dMike ReedDEFINE_TESTCLASS("Triangulation", TriangulationTestClass, TestTriangulation)
300