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 10 namespace SimplifyAngleTest { 11 12 #include "Simplify.cpp" 13 14 } // end of SimplifyAngleTest namespace 15 16 #include "Intersection_Tests.h" 17 18 static 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 29 static const size_t lineCount = sizeof(lines) / sizeof(lines[0]); 30 31 static 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 41 static const size_t quadCount = sizeof(quads) / sizeof(quads[0]); 42 43 static 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 53 static const size_t cubicCount = sizeof(cubics) / sizeof(cubics[0]); 54 55 struct segment { 56 SkPath::Verb verb; 57 SkPoint pts[4]; 58 }; 59 60 static 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 68 static 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 75 static const segment segmentTest3[] = { 76 {SkPath::kQuad_Verb, {{0, 0}, {2, 0}, {0, 1}}}, 77 {SkPath::kQuad_Verb, {{0, 0}, {1, 0}, {0, 1}}}, 78 {SkPath::kMove_Verb } 79 }; 80 81 static const segment* segmentTests[] = { 82 segmentTest3, 83 segmentTest2, 84 segmentTest1, 85 }; 86 87 static const size_t segmentTestCount = sizeof(segmentTests) / sizeof(segmentTests[0]); 88 89 static void testSegments(bool testFlat) { 90 for (size_t testIndex = 0; testIndex < segmentTestCount; ++testIndex) { 91 const segment* segPtr = segmentTests[testIndex]; 92 SimplifyAngleTest::Angle lesser, greater; 93 int index = 0; 94 do { 95 int next = index + 1; 96 SkTDArray<SimplifyAngleTest::Span> dummy; 97 lesser.set(segPtr[index].pts, segPtr[index].verb, NULL, index, next, dummy); 98 if (segPtr[next].verb == SkPath::kMove_Verb) { 99 break; 100 } 101 greater.set(segPtr[next].pts, segPtr[next].verb, NULL, index, next, dummy); 102 bool result = lesser < greater; 103 SkASSERT(result); 104 index = next; 105 } while (true); 106 } 107 } 108 109 static void testLines(bool testFlat) { 110 // create angles in a circle 111 SkTDArray<SimplifyAngleTest::Angle> angles; 112 SkTDArray<SimplifyAngleTest::Angle* > angleList; 113 SkTDArray<double> arcTans; 114 size_t x; 115 for (x = 0; x < lineCount; ++x) { 116 SimplifyAngleTest::Angle* angle = angles.append(); 117 SkTDArray<SimplifyAngleTest::Span> dummy; 118 angle->set(lines[x], SkPath::kLine_Verb, 0, x, x + 1, dummy); 119 double arcTan = atan2(lines[x][0].fX - lines[x][1].fX, 120 lines[x][0].fY - lines[x][1].fY); 121 arcTans.push(arcTan); 122 } 123 for (x = 0; x < lineCount; ++x) { 124 angleList.push(&angles[x]); 125 } 126 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1); 127 bool first = true; 128 bool wrap = false; 129 double base, last; 130 for (size_t x = 0; x < lineCount; ++x) { 131 const SimplifyAngleTest::Angle* angle = angleList[x]; 132 int span = angle->start(); 133 // SkDebugf("%s [%d] %1.9g (%1.9g,%1.9g %1.9g,%1.9g)\n", __FUNCTION__, 134 // span, arcTans[span], lines[span][0].fX, lines[span][0].fY, 135 // lines[span][1].fX, lines[span][1].fY); 136 if (first) { 137 base = last = arcTans[span]; 138 first = false; 139 continue; 140 } 141 if (last < arcTans[span]) { 142 last = arcTans[span]; 143 continue; 144 } 145 if (!wrap) { 146 if (base < arcTans[span]) { 147 SkDebugf("%s !wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]); 148 SkASSERT(0); 149 } 150 last = arcTans[span]; 151 wrap = true; 152 continue; 153 } 154 SkDebugf("%s wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]); 155 SkASSERT(0); 156 } 157 } 158 159 static void testQuads(bool testFlat) { 160 SkTDArray<SimplifyAngleTest::Angle> angles; 161 SkTDArray<SimplifyAngleTest::Angle* > angleList; 162 size_t x; 163 for (x = 0; x < quadCount; ++x) { 164 SimplifyAngleTest::Angle* angle = angles.append(); 165 SkTDArray<SimplifyAngleTest::Span> dummy; 166 angle->set(quads[x], SkPath::kQuad_Verb, 0, x, x + 1, dummy); 167 } 168 for (x = 0; x < quadCount; ++x) { 169 angleList.push(&angles[x]); 170 } 171 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1); 172 for (size_t x = 0; x < quadCount; ++x) { 173 *angleList[x] < *angleList[x + 1]; 174 SkASSERT(x == quadCount - 1 || *angleList[x] < *angleList[x + 1]); 175 const SimplifyAngleTest::Angle* angle = angleList[x]; 176 if ((int) x != angle->start()) { 177 SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start()); 178 SkASSERT(0); 179 } 180 } 181 } 182 183 static void testCubics(bool testFlat) { 184 SkTDArray<SimplifyAngleTest::Angle> angles; 185 SkTDArray<SimplifyAngleTest::Angle* > angleList; 186 for (size_t x = 0; x < cubicCount; ++x) { 187 SimplifyAngleTest::Angle* angle = angles.append(); 188 SkTDArray<SimplifyAngleTest::Span> dummy; 189 angle->set(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1, dummy); 190 angleList.push(angle); 191 } 192 QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1); 193 for (size_t x = 0; x < cubicCount; ++x) { 194 const SimplifyAngleTest::Angle* angle = angleList[x]; 195 if ((int) x != angle->start()) { 196 SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start()); 197 SkASSERT(0); 198 } 199 } 200 } 201 202 struct segmentWithT { 203 SkPath::Verb verb; 204 SkPoint pts[4]; 205 double ts[2]; 206 }; 207 208 209 static const segmentWithT oneOffTest1[] = { 210 {SkPath::kQuad_Verb, {{391.653534f, 183.286819f}, {391.653534f, 157.724487f}, {405.469604f, 141.372879f}}, 211 {0.62346946335026932, 0.62344389027237135}}, 212 {SkPath::kQuad_Verb, {{399.365234f, 171.695801f}, {399.365234f, 140.337967f}, {375.976227f, 140.337967f}}, 213 {0.31638302676995866, 0.31637992418411398}}, 214 {SkPath::kMove_Verb } 215 }; 216 217 static const segmentWithT oneOffTest2[] = { 218 {SkPath::kQuad_Verb, {{399.070374f, 151.722f}, {391.101532f, 163.002533f}, {391.101532f, 182.665863f}}, 219 {0.13793711854916513, 0.13790171160614006}}, 220 {SkPath::kQuad_Verb, {{391.653534f, 183.286819f}, {391.653534f, 157.724487f}, {405.469604f, 141.372879f}}, 221 {0.62344389027237135, 0.62346946335026932}}, 222 {SkPath::kMove_Verb } 223 }; 224 225 static const segmentWithT oneOffTest3[] = { 226 {SkPath::kQuad_Verb, {{399.365234f, 171.695801f}, {399.365234f, 140.337967f}, {375.976227f, 140.337967f}}, 227 {0.31637992418411398, 0.31638302676995866, }}, 228 {SkPath::kQuad_Verb, {{399.070374f, 151.722f}, {391.101532f, 163.002533f}, {391.101532f, 182.665863f}}, 229 {0.13790171160614006, 0.13793711854916513}}, 230 {SkPath::kMove_Verb } 231 }; 232 233 static const segmentWithT oneOffTest4[] = { 234 {SkPath::kCubic_Verb, {{1,2}, {1,3}, {1,0}, {5,3}}, {0.134792, 0}}, 235 {SkPath::kCubic_Verb, {{0,1}, {3,5}, {2,1}, {3,1}}, {0.134792094, 0}}, 236 {SkPath::kCubic_Verb, {{0,1}, {3,5}, {2,1}, {3,1}}, {0.134792094, 0.551812363}}, 237 {SkPath::kCubic_Verb, {{1,2}, {1,3}, {1,0}, {5,3}}, {0.134792, 0.333333333}}, 238 {SkPath::kMove_Verb } 239 }; 240 241 static const segmentWithT* oneOffTests[] = { 242 oneOffTest1, 243 oneOffTest2, 244 oneOffTest3, 245 oneOffTest4, 246 }; 247 248 static const size_t oneOffTestCount = sizeof(oneOffTests) / sizeof(oneOffTests[0]); 249 250 static void oneOffTest(bool testFlat) { 251 for (size_t testIndex = 0; testIndex < oneOffTestCount; ++testIndex) { 252 const segmentWithT* segPtr = oneOffTests[testIndex]; 253 SimplifyAngleTest::Angle lesser, greater; 254 int index = 0; 255 do { 256 int next = index + 1; 257 SkTDArray<SimplifyAngleTest::Span> dummy; // FIXME 258 lesser.set(segPtr[index].pts, segPtr[index].verb, 0, index, next, dummy); // FIXME: segPtr[index].ts[0], segPtr[index].ts[1]); 259 if (segPtr[next].verb == SkPath::kMove_Verb) { 260 break; 261 } 262 greater.set(segPtr[next].pts, segPtr[next].verb, 0, index, next, dummy); // FIXME: segPtr[next].ts[0], segPtr[next].ts[1]); 263 bool result = lesser < greater; 264 SkASSERT(result); 265 index = next; 266 } while (true); 267 } 268 SkDebugf("%s finished\n", __FUNCTION__); 269 } 270 271 #if 0 // seems too complicated for this to be useful (didn't finish writing/debugging this) 272 // this (trys to) take a pair of curves, construct segments/spans, and verify that they sort correctly 273 static void oneOffTestNew() { 274 const segmentWithT* segPtr = oneOffTest4; 275 SimplifyAngleTest::Segment segOne, segTwo; 276 segOne.init(segPtr[0].pts, segPtr[0].verb, false, false); 277 segTwo.init(segPtr[1].pts, segPtr[1].verb, false, false); 278 int index = 0; 279 do { 280 int next = index + 1; 281 if (segPtr[index].verb == SkPath::kMove_Verb) { 282 break; 283 } 284 SkPoint sub[4]; 285 (*SegmentSubDivide[segPtr[index].verb])(segPtr[index].pts, segPtr[index].ts[0], 286 segPtr[index].ts[1], sub); 287 if (memcmp(segPtr[index].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[index].verb + 1) == 0) { 288 segOne.addT(&segTwo, sub[0], segPtr[index].ts[0]); 289 segOne.addT(&segTwo, sub[segPtr[index].verb], segPtr[index].ts[1]); 290 } else { 291 segTwo.addT(&segOne, sub[0], segPtr[index].ts[0]); 292 segTwo.addT(&v, sub[segPtr[index].verb], segPtr[index].ts[1]); 293 } 294 } while (true); 295 SimplifyAngleTest::Angle lesser, greater; 296 do { 297 int next = index + 1; 298 if (segPtr[next].verb == SkPath::kMove_Verb) { 299 break; 300 } 301 SkPoint one[4], two[4]; 302 bool use1 = memcmp(segPtr[index].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[index].verb + 1) == 0; 303 lesser.set(segPtr[index].pts, segPtr[index].verb, use1 ? &segOne : &segTwo, index, next, dummy); 304 use1 = memcmp(segPtr[next].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[next].verb + 1) == 0; 305 greater.set(segPtr[next].pts, segPtr[next].verb, use1 ? &segOne : &segTwo, index, next, dummy); 306 bool result = lesser < greater; 307 SkASSERT(result); 308 index = next; 309 } while (true); 310 SkDebugf("%s finished\n", __FUNCTION__); 311 } 312 #endif 313 314 static void (*tests[])(bool) = { 315 oneOffTest, 316 testSegments, 317 testLines, 318 testQuads, 319 testCubics 320 }; 321 322 static const size_t testCount = sizeof(tests) / sizeof(tests[0]); 323 324 static void (*firstTest)(bool) = 0; 325 static bool skipAll = false; 326 327 void SimplifyAngle_Test() { 328 if (skipAll) { 329 return; 330 } 331 size_t index = 0; 332 if (firstTest) { 333 while (index < testCount && tests[index] != firstTest) { 334 ++index; 335 } 336 } 337 bool firstTestComplete = false; 338 for ( ; index < testCount; ++index) { 339 (*tests[index])(false); // set to true to exercise setFlat 340 firstTestComplete = true; 341 } 342 } 343