blob: 1228a771e9953cb50715cb5a3b2d17f52ca4f622 [file] [log] [blame]
caryclark@google.comb45a1b42012-05-18 20:50:33 +00001/*
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 SimplifyAngleTest {
11
12#include "Simplify.cpp"
13
14} // end of SimplifyAngleTest namespace
15
16#include "Intersection_Tests.h"
17
18static const SkPoint lines[][2] = {
19 { { 10, 10}, { 10, 20} },
20 { { 10, 10}, { 20, 10} },
21 { { 10, 10}, {-20, 10} },
22 { { 10, 10}, { 10, -20} },
23 { { 10, 10}, { 20, 20} },
24 { { 10, 10}, {-20, -20} },
25 { { 10, 10}, {-20, 40} },
26 { { 10, 10}, { 40, -20} }
27};
28
29static const size_t lineCount = sizeof(lines) / sizeof(lines[0]);
30
31static const SkPoint quads[][3] = {
32 {{ 1, 1}, { 2, 2}, { 1, 3}}, // 0
33 {{ 1, 1}, { 3, 3}, { 1, 5}}, // 1
34 {{ 1, 1}, { 4, 4}, { 1, 7}}, // 2
35 {{ 1, 1}, { 5, 5}, { 9, 9}}, // 3
36 {{ 1, 1}, { 4, 4}, { 7, 1}}, // 4
37 {{ 1, 1}, { 3, 3}, { 5, 1}}, // 5
38 {{ 1, 1}, { 2, 2}, { 3, 1}}, // 6
39};
40
41static const size_t quadCount = sizeof(quads) / sizeof(quads[0]);
42
43static const SkPoint cubics[][4] = {
44 {{ 1, 1}, { 2, 2}, { 2, 3}, { 1, 4}},
45 {{ 1, 1}, { 3, 3}, { 3, 5}, { 1, 7}},
46 {{ 1, 1}, { 4, 4}, { 4, 7}, { 1, 10}},
47 {{ 1, 1}, { 5, 5}, { 8, 8}, { 9, 9}},
48 {{ 1, 1}, { 4, 4}, { 7, 4}, { 10, 1}},
49 {{ 1, 1}, { 3, 3}, { 5, 3}, { 7, 1}},
50 {{ 1, 1}, { 2, 2}, { 3, 2}, { 4, 1}},
51};
52
53static const size_t cubicCount = sizeof(cubics) / sizeof(cubics[0]);
54
caryclark@google.comc899ad92012-08-23 15:24:42 +000055struct segment {
56 SkPath::Verb verb;
57 SkPoint pts[4];
58};
59
60static const segment segmentTest1[] = {
61 {SkPath::kLine_Verb, {{2, 1}, {1, 0} }},
62 {SkPath::kQuad_Verb, {{2, 1}, {1, 0}, {0, 0}}},
63 {SkPath::kQuad_Verb, {{2, 1}, {3, 2}, {2, 3}}},
64 {SkPath::kLine_Verb, {{2, 1}, {3, 2} }},
65 {SkPath::kMove_Verb }
66};
67
caryclark@google.com3350c3c2012-08-24 15:24:36 +000068static const segment segmentTest2[] = {
69 {SkPath::kLine_Verb, {{1, 0}, {0, 0} }},
70 {SkPath::kQuad_Verb, {{1, 0}, {1.89897954f, 0.898979485f}, {2.39387703f, 1.59591794f}}},
71 {SkPath::kLine_Verb, {{1, 0}, {3, 2} }},
72 {SkPath::kMove_Verb }
73};
74
caryclark@google.comc899ad92012-08-23 15:24:42 +000075static const segment* segmentTests[] = {
caryclark@google.com3350c3c2012-08-24 15:24:36 +000076 segmentTest2,
77 segmentTest1,
caryclark@google.comc899ad92012-08-23 15:24:42 +000078};
79
80static const size_t segmentTestCount = sizeof(segmentTests) / sizeof(segmentTests[0]);
81
82static void testSegments(bool testFlat) {
83 for (size_t testIndex = 0; testIndex < segmentTestCount; ++testIndex) {
84 const segment* segPtr = segmentTests[testIndex];
85 SimplifyAngleTest::Angle lesser, greater;
86 int index = 0;
87 do {
88 int next = index + 1;
caryclark@google.com3350c3c2012-08-24 15:24:36 +000089 #if HIGH_DEF_ANGLES==0
caryclark@google.comc899ad92012-08-23 15:24:42 +000090 if (testFlat) {
91 lesser.setFlat(segPtr[index].pts, segPtr[index].verb, 0, index, next);
92 } else {
93 lesser.set(segPtr[index].pts, segPtr[index].verb, 0, index, next);
94 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +000095 #else
96 lesser.set(segPtr[index].pts, segPtr[index].verb, 0, index, next, 0, 1);
97 #endif
caryclark@google.comc899ad92012-08-23 15:24:42 +000098 if (segPtr[next].verb == SkPath::kMove_Verb) {
99 break;
100 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000101 #if HIGH_DEF_ANGLES==0
caryclark@google.comc899ad92012-08-23 15:24:42 +0000102 if (testFlat) {
103 greater.setFlat(segPtr[next].pts, segPtr[next].verb, 0, index, next);
104 } else {
105 greater.set(segPtr[next].pts, segPtr[next].verb, 0, index, next);
106 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000107 #else
108 greater.set(segPtr[next].pts, segPtr[next].verb, 0, index, next, 0, 1);
109 #endif
caryclark@google.comc899ad92012-08-23 15:24:42 +0000110 bool result = lesser < greater;
111 SkASSERT(result);
112 index = next;
113 } while (true);
114 }
115}
116
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000117static void testLines(bool testFlat) {
118 // create angles in a circle
119 SkTDArray<SimplifyAngleTest::Angle> angles;
120 SkTDArray<SimplifyAngleTest::Angle* > angleList;
121 SkTDArray<double> arcTans;
122 size_t x;
123 for (x = 0; x < lineCount; ++x) {
124 SimplifyAngleTest::Angle* angle = angles.append();
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000125 #if HIGH_DEF_ANGLES==0
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000126 if (testFlat) {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000127 angle->setFlat(lines[x], SkPath::kLine_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000128 } else {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000129 angle->set(lines[x], SkPath::kLine_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000130 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000131 #else
132 angle->set(lines[x], SkPath::kLine_Verb, 0, x, x + 1, 0, 1);
133 #endif
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000134 double arcTan = atan2(lines[x][0].fX - lines[x][1].fX,
135 lines[x][0].fY - lines[x][1].fY);
136 arcTans.push(arcTan);
137 }
138 for (x = 0; x < lineCount; ++x) {
139 angleList.push(&angles[x]);
140 }
141 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
142 bool first = true;
143 bool wrap = false;
144 double base, last;
145 for (size_t x = 0; x < lineCount; ++x) {
146 const SimplifyAngleTest::Angle* angle = angleList[x];
147 int span = angle->start();
148// SkDebugf("%s [%d] %1.9g (%1.9g,%1.9g %1.9g,%1.9g)\n", __FUNCTION__,
149// span, arcTans[span], lines[span][0].fX, lines[span][0].fY,
150// lines[span][1].fX, lines[span][1].fY);
151 if (first) {
152 base = last = arcTans[span];
153 first = false;
154 continue;
155 }
156 if (last < arcTans[span]) {
157 last = arcTans[span];
158 continue;
159 }
160 if (!wrap) {
161 if (base < arcTans[span]) {
162 SkDebugf("%s !wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
163 SkASSERT(0);
164 }
165 last = arcTans[span];
166 wrap = true;
167 continue;
168 }
169 SkDebugf("%s wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
170 SkASSERT(0);
171 }
172}
173
174static void testQuads(bool testFlat) {
175 SkTDArray<SimplifyAngleTest::Angle> angles;
176 SkTDArray<SimplifyAngleTest::Angle* > angleList;
177 size_t x;
178 for (x = 0; x < quadCount; ++x) {
179 SimplifyAngleTest::Angle* angle = angles.append();
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000180 #if HIGH_DEF_ANGLES==0
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000181 if (testFlat) {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000182 angle->setFlat(quads[x], SkPath::kQuad_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000183 } else {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000184 angle->set(quads[x], SkPath::kQuad_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000185 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000186 #else
187 angle->set(quads[x], SkPath::kQuad_Verb, 0, x, x + 1, 0, 1);
188 #endif
189 }
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000190 for (x = 0; x < quadCount; ++x) {
191 angleList.push(&angles[x]);
192 }
193 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
194 for (size_t x = 0; x < quadCount; ++x) {
195 *angleList[x] < *angleList[x + 1];
196 SkASSERT(x == quadCount - 1 || *angleList[x] < *angleList[x + 1]);
197 const SimplifyAngleTest::Angle* angle = angleList[x];
caryclark@google.comf25edfe2012-06-01 18:20:10 +0000198 if ((int) x != angle->start()) {
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000199 SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
200 SkASSERT(0);
201 }
202 }
203}
204
205static void testCubics(bool testFlat) {
206 SkTDArray<SimplifyAngleTest::Angle> angles;
207 SkTDArray<SimplifyAngleTest::Angle* > angleList;
208 for (size_t x = 0; x < cubicCount; ++x) {
209 SimplifyAngleTest::Angle* angle = angles.append();
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000210 #if HIGH_DEF_ANGLES==0
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000211 if (testFlat) {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000212 angle->setFlat(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000213 } else {
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000214 angle->set(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1);
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000215 }
caryclark@google.com3350c3c2012-08-24 15:24:36 +0000216 #else
217 angle->set(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1, 0, 1);
218 #endif
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000219 angleList.push(angle);
220 }
221 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
222 for (size_t x = 0; x < cubicCount; ++x) {
223 const SimplifyAngleTest::Angle* angle = angleList[x];
caryclark@google.comf25edfe2012-06-01 18:20:10 +0000224 if ((int) x != angle->start()) {
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000225 SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
226 SkASSERT(0);
227 }
228 }
229}
230
231static void (*tests[])(bool) = {
caryclark@google.comc899ad92012-08-23 15:24:42 +0000232 testSegments,
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000233 testLines,
234 testQuads,
235 testCubics
236};
237
238static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
239
240static void (*firstTest)(bool) = 0;
241static bool skipAll = false;
242
243void SimplifyAngle_Test() {
244 if (skipAll) {
245 return;
246 }
247 size_t index = 0;
248 if (firstTest) {
249 while (index < testCount && tests[index] != firstTest) {
250 ++index;
251 }
252 }
253 bool firstTestComplete = false;
254 for ( ; index < testCount; ++index) {
caryclark@google.comc899ad92012-08-23 15:24:42 +0000255 (*tests[index])(false); // set to true to exercise setFlat
caryclark@google.comb45a1b42012-05-18 20:50:33 +0000256 firstTestComplete = true;
257 }
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000258}