1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Simplify.h"
9
10namespace SimplifyFindTopTest {
11
12#include "Simplify.cpp"
13
14} // end of SimplifyFindTopTest namespace
15
16#include "Intersection_Tests.h"
17
18static const SimplifyFindTopTest::Segment* testCommon(
19        SkTArray<SimplifyFindTopTest::Contour>& contours,
20        int& index, int& end) {
21    SkTDArray<SimplifyFindTopTest::Contour*> contourList;
22    makeContourList(contours, contourList, false, false);
23    addIntersectTs(contourList[0], contourList[0]);
24    if (contours.count() > 1) {
25        SkASSERT(contours.count() == 2);
26        addIntersectTs(contourList[0], contourList[1]);
27        addIntersectTs(contourList[1], contourList[1]);
28    }
29    fixOtherTIndex(contourList);
30#if SORTABLE_CONTOURS // old way
31    SimplifyFindTopTest::Segment* topStart = findTopContour(contourList);
32    const SimplifyFindTopTest::Segment* topSegment = topStart->findTop(index,
33            end);
34#else
35    SkPoint bestXY = {SK_ScalarMin, SK_ScalarMin};
36    bool done, unsortable = false;
37    const SimplifyFindTopTest::Segment* topSegment =
38            findSortableTop(contourList, index, end, bestXY, unsortable, done, true);
39#endif
40    return topSegment;
41}
42
43static void test(const SkPath& path) {
44    SkTArray<SimplifyFindTopTest::Contour> contours;
45    SimplifyFindTopTest::EdgeBuilder builder(path, contours);
46    int index, end;
47    testCommon(contours, index, end);
48    SkASSERT(index + 1 == end);
49}
50
51static void test(const SkPath& path, SkScalar x1, SkScalar y1,
52        SkScalar x2, SkScalar y2) {
53    SkTArray<SimplifyFindTopTest::Contour> contours;
54    SimplifyFindTopTest::EdgeBuilder builder(path, contours);
55    int index, end;
56    const SimplifyFindTopTest::Segment* topSegment =
57            testCommon(contours, index, end);
58    SkPoint pts[2];
59    double firstT = topSegment->t(index);
60    pts[0] = topSegment->xyAtT(&topSegment->span(index));
61    int direction = index < end ? 1 : -1;
62    do {
63        index += direction;
64        double nextT = topSegment->t(index);
65        if (nextT == firstT) {
66            continue;
67        }
68        pts[1] = topSegment->xyAtT(&topSegment->span(index));
69        if (pts[0] != pts[1]) {
70            break;
71        }
72    } while (true);
73    SkASSERT(pts[0].fX == x1);
74    SkASSERT(pts[0].fY == y1);
75    SkASSERT(pts[1].fX == x2);
76    SkASSERT(pts[1].fY == y2);
77}
78
79static void testLine1() {
80    SkPath path;
81    path.moveTo(2,0);
82    path.lineTo(1,1);
83    path.lineTo(0,0);
84    path.close();
85    test(path);
86}
87
88static void addInnerCWTriangle(SkPath& path) {
89    path.moveTo(3,0);
90    path.lineTo(4,1);
91    path.lineTo(2,1);
92    path.close();
93}
94
95static void addInnerCCWTriangle(SkPath& path) {
96    path.moveTo(3,0);
97    path.lineTo(2,1);
98    path.lineTo(4,1);
99    path.close();
100}
101
102static void addOuterCWTriangle(SkPath& path) {
103    path.moveTo(3,0);
104    path.lineTo(6,2);
105    path.lineTo(0,2);
106    path.close();
107}
108
109static void addOuterCCWTriangle(SkPath& path) {
110    path.moveTo(3,0);
111    path.lineTo(0,2);
112    path.lineTo(6,2);
113    path.close();
114}
115
116static void testLine2() {
117    SkPath path;
118    addInnerCWTriangle(path);
119    addOuterCWTriangle(path);
120    test(path, 0, 2, 3, 0);
121}
122
123static void testLine3() {
124    SkPath path;
125    addOuterCWTriangle(path);
126    addInnerCWTriangle(path);
127    test(path, 0, 2, 3, 0);
128}
129
130static void testLine4() {
131    SkPath path;
132    addInnerCCWTriangle(path);
133    addOuterCWTriangle(path);
134    test(path, 0, 2, 3, 0);
135}
136
137static void testLine5() {
138    SkPath path;
139    addOuterCWTriangle(path);
140    addInnerCCWTriangle(path);
141    test(path, 0, 2, 3, 0);
142}
143
144static void testLine6() {
145    SkPath path;
146    addInnerCWTriangle(path);
147    addOuterCCWTriangle(path);
148    test(path, 0, 2, 3, 0);
149}
150
151static void testLine7() {
152    SkPath path;
153    addOuterCCWTriangle(path);
154    addInnerCWTriangle(path);
155    test(path, 0, 2, 3, 0);
156}
157
158static void testLine8() {
159    SkPath path;
160    addInnerCCWTriangle(path);
161    addOuterCCWTriangle(path);
162    test(path, 0, 2, 3, 0);
163}
164
165static void testLine9() {
166    SkPath path;
167    addOuterCCWTriangle(path);
168    addInnerCCWTriangle(path);
169    test(path, 0, 2, 3, 0);
170}
171
172static void testQuads() {
173    SkPath path;
174    path.moveTo(2,0);
175    path.quadTo(1,1, 0,0);
176    path.close();
177    test(path);
178}
179
180static void testCubics() {
181    SkPath path;
182    path.moveTo(2,0);
183    path.cubicTo(2,3, 1,1, 0,0);
184    path.close();
185    test(path);
186}
187
188static void (*tests[])() = {
189    testLine1,
190    testLine2,
191    testLine3,
192    testLine4,
193    testLine5,
194    testLine6,
195    testLine7,
196    testLine8,
197    testLine9,
198    testQuads,
199    testCubics
200};
201
202static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
203
204static void (*firstTest)() = 0;
205static bool skipAll = false;
206
207void SimplifyFindTop_Test() {
208    if (skipAll) {
209        return;
210    }
211    size_t index = 0;
212    if (firstTest) {
213        while (index < testCount && tests[index] != firstTest) {
214            ++index;
215        }
216    }
217    bool firstTestComplete = false;
218    for ( ; index < testCount; ++index) {
219        (*tests[index])();
220        firstTestComplete = true;
221    }
222}
223