OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "PathOpsTestCommon.h" | 7 #include "PathOpsTestCommon.h" |
| 8 #include "SkIntersections.h" |
8 #include "SkOpSegment.h" | 9 #include "SkOpSegment.h" |
| 10 #include "SkPathOpsTriangle.h" |
| 11 #include "SkRandom.h" |
9 #include "SkTArray.h" | 12 #include "SkTArray.h" |
| 13 #include "SkTSort.h" |
10 #include "Test.h" | 14 #include "Test.h" |
11 | 15 |
| 16 static bool gDisableAngleTests = true; |
| 17 |
12 static const SkPoint cubics[][4] = { | 18 static const SkPoint cubics[][4] = { |
13 /* 0 */ {{0, 1}, {2, 6}, {4, 2}, {5, 3}}, | 19 /* 0 */ {{0, 1}, {2, 6}, {4, 2}, {5, 3}}, |
14 /* 1 */ {{10, 234}, {10, 229.581726f}, {13.5817204f, 226}, {18, 226}}, | 20 /* 1 */ {{10, 234}, {10, 229.581726f}, {13.5817204f, 226}, {18, 226}}, |
15 /* 2 */ {{132, 11419}, {130.89543151855469f, 11419}, {130, 11418.1044921875f}
, {130, 11417}}, | 21 /* 2 */ {{132, 11419}, {130.89543151855469f, 11419}, {130, 11418.1044921875f}
, {130, 11417}}, |
16 /* 3 */ {{130.04275512695312f, 11417.4130859375f}, {130.23307800292969f, 1141
8.3193359375f}, | 22 /* 3 */ {{130.04275512695312f, 11417.4130859375f}, {130.23307800292969f, 1141
8.3193359375f}, |
17 {131.03709411621094f, 11419}, {132, 11419}}, | 23 {131.03709411621094f, 11419}, {132, 11419}}, |
18 /* 4 */ {{0,1}, {0,5}, {4,1}, {6,4}}, | 24 /* 4 */ {{0,1}, {0,5}, {4,1}, {6,4}}, |
19 /* 5 */ {{1,5}, {4,6}, {1,0}, {4,0}}, | 25 /* 5 */ {{1,5}, {4,6}, {1,0}, {4,0}}, |
20 /* 6 */ {{0,1}, {0,4}, {5,1}, {6,4}}, | 26 /* 6 */ {{0,1}, {0,4}, {5,1}, {6,4}}, |
21 /* 7 */ {{0,1}, {1,2}, {1,0}, {6,1}}, | 27 /* 7 */ {{0,1}, {1,2}, {1,0}, {6,1}}, |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 { TEST_ENTRY(set5), {0, 0}}, | 237 { TEST_ENTRY(set5), {0, 0}}, |
232 // { TEST_ENTRY(set4), {0, 0}}, | 238 // { TEST_ENTRY(set4), {0, 0}}, |
233 { TEST_ENTRY(set3), {0, 0}}, | 239 { TEST_ENTRY(set3), {0, 0}}, |
234 { TEST_ENTRY(set2), {0, 0}}, | 240 { TEST_ENTRY(set2), {0, 0}}, |
235 // { TEST_ENTRY(set1a), {3.70370364f,3.14814806f} }, | 241 // { TEST_ENTRY(set1a), {3.70370364f,3.14814806f} }, |
236 // { TEST_ENTRY(set1), {0, 0}}, | 242 // { TEST_ENTRY(set1), {0, 0}}, |
237 }; | 243 }; |
238 | 244 |
239 #undef TEST_ENTRY | 245 #undef TEST_ENTRY |
240 | 246 |
241 static void setup(const SortSet* set, const size_t idx, | 247 static float next(float f) |
242 SkOpSegment* seg, int* ts, const SkPoint& startPt) { | 248 { |
243 SkPoint start, end; | 249 int fBits = SkFloatAs2sCompliment(f); |
244 const SkPoint* data = set[idx].ptData; | 250 ++fBits; |
245 bool useIntersectPt = startPt.fX != 0 || startPt.fY != 0; | 251 float fNext = Sk2sComplimentAsFloat(fBits); |
246 if (useIntersectPt) { | 252 return fNext; |
247 start = startPt; | |
248 end = set[idx].endPt; | |
249 } | |
250 switch(set[idx].ptCount) { | |
251 case 2: { | |
252 SkASSERT(ValidPoints(data, 2)); | |
253 seg->addLine(data, false, false); | |
254 SkDLine dLine; | |
255 dLine.set(set[idx].ptData); | |
256 SkASSERT(ValidLine(dLine)); | |
257 if (useIntersectPt) { | |
258 break; | |
259 } | |
260 start = dLine.ptAtT(set[idx].tStart).asSkPoint(); | |
261 end = dLine.ptAtT(set[idx].tEnd).asSkPoint(); | |
262 } break; | |
263 case 3: { | |
264 SkASSERT(ValidPoints(data, 3)); | |
265 seg->addQuad(data, false, false); | |
266 SkDQuad dQuad; | |
267 dQuad.set(set[idx].ptData); | |
268 SkASSERT(ValidQuad(dQuad)); | |
269 if (useIntersectPt) { | |
270 break; | |
271 } | |
272 start = dQuad.ptAtT(set[idx].tStart).asSkPoint(); | |
273 end = dQuad.ptAtT(set[idx].tEnd).asSkPoint(); | |
274 } break; | |
275 case 4: { | |
276 SkASSERT(ValidPoints(data, 4)); | |
277 seg->addCubic(data, false, false); | |
278 SkDCubic dCubic; | |
279 dCubic.set(set[idx].ptData); | |
280 SkASSERT(ValidCubic(dCubic)); | |
281 if (useIntersectPt) { | |
282 break; | |
283 } | |
284 start = dCubic.ptAtT(set[idx].tStart).asSkPoint(); | |
285 end = dCubic.ptAtT(set[idx].tEnd).asSkPoint(); | |
286 } break; | |
287 } | |
288 double tStart = set[idx].tStart; | |
289 double tEnd = set[idx].tEnd; | |
290 seg->addT(NULL, start, tStart); | |
291 seg->addT(NULL, end, tEnd); | |
292 if (tStart != 0 && tEnd != 0) { | |
293 seg->addT(NULL, set[idx].ptData[0], 0); | |
294 } | |
295 if (tStart != 1 && tEnd != 1) { | |
296 seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1); | |
297 } | |
298 int tIndex = 0; | |
299 ts[0] = 0; | |
300 ts[1] = 1; | |
301 do { | |
302 if (seg->t(tIndex) == set[idx].tStart) { | |
303 ts[0] = tIndex; | |
304 } | |
305 if (seg->t(tIndex) == set[idx].tEnd) { | |
306 ts[1] = tIndex; | |
307 } | |
308 if (seg->t(tIndex) >= 1) { | |
309 break; | |
310 } | |
311 } while (++tIndex); | |
312 } | 253 } |
313 | 254 |
314 static void testOne(skiatest::Reporter* reporter, const SortSetTests& test) { | 255 static float prev(float f) |
315 SkTDArray<SkOpAngle> angles; | 256 { |
316 bool unsortable = false; | 257 int fBits = SkFloatAs2sCompliment(f); |
317 bool unorderable = false; | 258 --fBits; |
318 SkTArray<SkOpSegment> segs; | 259 float fNext = Sk2sComplimentAsFloat(fBits); |
319 for (size_t idx = 0; idx < test.count; ++idx) { | 260 return fNext; |
320 int ts[2]; | 261 } |
321 const SortSet* set = test.set; | 262 |
322 SkOpSegment& seg = segs.push_back(); | 263 DEF_TEST(PathOpsAngleFindCrossEpsilon, reporter) { |
323 setup(set, idx, &seg, ts, test.startPt); | 264 if (gDisableAngleTests) { |
324 SkOpAngle* angle = angles.append(); | |
325 angle->set(&seg, ts[0], ts[1]); | |
326 #if DEBUG_ANGLE | |
327 angle->setID(idx); | |
328 #endif | |
329 if (angle->unsortable()) { | |
330 #if DEBUG_ANGLE | |
331 SkDebugf("%s test[%s]: angle[%d] unsortable\n", __FUNCTION__, test.
name, idx); | |
332 #endif | |
333 unsortable = true; | |
334 } | |
335 if (angle->unorderable()) { | |
336 #if DEBUG_ANGLE | |
337 SkDebugf("%s test[%s]: angle[%d] unorderable\n", __FUNCTION__, test
.name, idx); | |
338 #endif | |
339 unorderable = true; | |
340 } | |
341 reporter->bumpTestCount(); | |
342 } | |
343 if (unsortable || unorderable) { | |
344 return; | 265 return; |
345 } | 266 } |
346 #if DEBUG_ANGLE | 267 SkRandom ran; |
347 SkDebugf("%s test[%s]\n", __FUNCTION__, test.name); | 268 int maxEpsilon = 0; |
348 #endif | 269 for (int index = 0; index < 10000000; ++index) { |
349 for (size_t idxL = 0; idxL < test.count; ++idxL) { | 270 SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(
0.0001f, 1000)}}}; |
350 const SkOpAngle& first = angles[idxL]; | 271 for (int inner = 0; inner < 10; ++inner) { |
351 for (size_t idxG = 0; idxG < test.count; ++idxG) { | 272 float t = ran.nextRangeF(0.0001f, 1); |
352 if (idxL == idxG) { | 273 SkDPoint dPt = line.ptAtT(t); |
353 continue; | 274 SkPoint pt = dPt.asSkPoint(); |
354 } | 275 float xs[3] = { prev(pt.fX), pt.fX, next(pt.fX) }; |
355 const SkOpAngle& second = angles[idxG]; | 276 float ys[3] = { prev(pt.fY), pt.fY, next(pt.fY) }; |
356 bool compare = first < second; | 277 for (int xIdx = 0; xIdx < 3; ++xIdx) { |
357 if (idxL < idxG) { | 278 for (int yIdx = 0; yIdx < 3; ++yIdx) { |
358 if (!compare) { | 279 SkPoint test = { xs[xIdx], ys[yIdx] }; |
359 SkDebugf("%s test[%s]: first[%d] > second[%d]\n", __FUNCTIO
N__, | 280 float p1 = SkDoubleToScalar(line[1].fX * test.fY); |
360 test.name, idxL, idxG); | 281 float p2 = SkDoubleToScalar(line[1].fY * test.fX); |
361 compare = first < second; | 282 int p1Bits = SkFloatAs2sCompliment(p1); |
| 283 int p2Bits = SkFloatAs2sCompliment(p2); |
| 284 int epsilon = abs(p1Bits - p2Bits); |
| 285 if (maxEpsilon < epsilon) { |
| 286 SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g pt={%1.7
g, %1.7g}" |
| 287 " epsilon=%d\n", |
| 288 line[1].fX, line[1].fY, t, test.fX, test.fY, epsilon
); |
| 289 maxEpsilon = epsilon; |
| 290 } |
362 } | 291 } |
363 REPORTER_ASSERT(reporter, compare); | |
364 } else { | |
365 SkASSERT(idxL > idxG); | |
366 if (compare) { | |
367 SkDebugf("%s test[%s]: first[%d] < second[%d]\n", __FUNCTIO
N__, | |
368 test.name, idxL, idxG); | |
369 compare = first < second; | |
370 } | |
371 REPORTER_ASSERT(reporter, !compare); | |
372 } | |
373 compare = second < first; | |
374 if (idxL < idxG) { | |
375 if (compare) { | |
376 SkDebugf("%s test[%s]: second[%d] < first[%d]\n", __FUNCTIO
N__, | |
377 test.name, idxL, idxG); | |
378 compare = second < first; | |
379 } | |
380 REPORTER_ASSERT(reporter, !compare); | |
381 } else { | |
382 SkASSERT(idxL > idxG); | |
383 if (!compare) { | |
384 SkDebugf("%s test[%s]: second[%d] > first[%d]\n", __FUNCTIO
N__, | |
385 test.name, idxL, idxG); | |
386 compare = second < first; | |
387 } | |
388 REPORTER_ASSERT(reporter, compare); | |
389 } | 292 } |
390 } | 293 } |
391 } | 294 } |
392 } | 295 } |
393 | 296 |
394 DEF_TEST(PathOpsAngle, reporter) { | 297 DEF_TEST(PathOpsAngleFindQuadEpsilon, reporter) { |
395 for (size_t index = 0; index < SK_ARRAY_COUNT(tests); ++index) { | 298 if (gDisableAngleTests) { |
396 const SortSetTests& test = tests[index]; | 299 return; |
397 testOne(reporter, test); | 300 } |
398 reporter->bumpTestCount(); | 301 SkRandom ran; |
| 302 int maxEpsilon = 0; |
| 303 double maxAngle = 0; |
| 304 for (int index = 0; index < 100000; ++index) { |
| 305 SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(
0.0001f, 1000)}}}; |
| 306 float t = ran.nextRangeF(0.0001f, 1); |
| 307 SkDPoint dPt = line.ptAtT(t); |
| 308 float t2 = ran.nextRangeF(0.0001f, 1); |
| 309 SkDPoint qPt = line.ptAtT(t2); |
| 310 float t3 = ran.nextRangeF(0.0001f, 1); |
| 311 SkDPoint qPt2 = line.ptAtT(t3); |
| 312 qPt.fX += qPt2.fY; |
| 313 qPt.fY -= qPt2.fX; |
| 314 SkDQuad quad = {{line[0], dPt, qPt}}; |
| 315 // binary search for maximum movement of quad[1] towards test that still
has 1 intersection |
| 316 double moveT = 0.5f; |
| 317 double deltaT = moveT / 2; |
| 318 SkDPoint last; |
| 319 do { |
| 320 last = quad[1]; |
| 321 quad[1].fX = dPt.fX - line[1].fY * moveT; |
| 322 quad[1].fY = dPt.fY + line[1].fX * moveT; |
| 323 SkIntersections i; |
| 324 i.intersect(quad, line); |
| 325 REPORTER_ASSERT(reporter, i.used() > 0); |
| 326 if (i.used() == 1) { |
| 327 moveT += deltaT; |
| 328 } else { |
| 329 moveT -= deltaT; |
| 330 } |
| 331 deltaT /= 2; |
| 332 } while (last.asSkPoint() != quad[1].asSkPoint()); |
| 333 float p1 = SkDoubleToScalar(line[1].fX * last.fY); |
| 334 float p2 = SkDoubleToScalar(line[1].fY * last.fX); |
| 335 int p1Bits = SkFloatAs2sCompliment(p1); |
| 336 int p2Bits = SkFloatAs2sCompliment(p2); |
| 337 int epsilon = abs(p1Bits - p2Bits); |
| 338 if (maxEpsilon < epsilon) { |
| 339 SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1
.7g" |
| 340 " pt={%1.7g, %1.7g} epsilon=%d\n", |
| 341 line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY,
epsilon); |
| 342 maxEpsilon = epsilon; |
| 343 } |
| 344 double a1 = atan2(line[1].fY, line[1].fX); |
| 345 double a2 = atan2(last.fY, last.fX); |
| 346 double angle = fabs(a1 - a2); |
| 347 if (maxAngle < angle) { |
| 348 SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1
.7g" |
| 349 " pt={%1.7g, %1.7g} angle=%1.7g\n", |
| 350 line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY,
angle); |
| 351 maxAngle = angle; |
| 352 } |
399 } | 353 } |
400 } | 354 } |
401 | 355 |
402 DEF_TEST(PathOpsAngleTestOne, reporter) { | |
403 size_t index = 0; | |
404 const SortSetTests& test = tests[index]; | |
405 testOne(reporter, test); | |
406 } | |
407 | |
408 #if 0 | |
409 static int find_slop(double x, double y, double rx, double ry) { | 356 static int find_slop(double x, double y, double rx, double ry) { |
410 int slopBits = 0; | 357 int slopBits = 0; |
411 bool less1, less2; | 358 bool less1, less2; |
412 double absX = fabs(x); | 359 double absX = fabs(x); |
413 double absY = fabs(y); | 360 double absY = fabs(y); |
414 double length = absX < absY ? absX / 2 + absY : absX + absY / 2; | 361 double length = absX < absY ? absX / 2 + absY : absX + absY / 2; |
415 int exponent; | 362 int exponent; |
416 (void) frexp(length, &exponent); | 363 (void) frexp(length, &exponent); |
417 double epsilon = ldexp(FLT_EPSILON, exponent); | 364 double epsilon = ldexp(FLT_EPSILON, exponent); |
418 do { | 365 do { |
(...skipping 25 matching lines...) Expand all Loading... |
444 return (x < 0 ? 2-y/(-x-y) : 3+x/(x-y)); | 391 return (x < 0 ? 2-y/(-x-y) : 3+x/(x-y)); |
445 } | 392 } |
446 | 393 |
447 static const double slopTests[][4] = { | 394 static const double slopTests[][4] = { |
448 // x y rx ry | 395 // x y rx ry |
449 {-0.058554756452593892, -0.18804585843827226, -0.018568569646021160, -0.0596
15294434479438}, | 396 {-0.058554756452593892, -0.18804585843827226, -0.018568569646021160, -0.0596
15294434479438}, |
450 {-0.0013717412948608398, 0.0041152238845825195, -0.00045837944195925573, 0.0
013753175735478074}, | 397 {-0.0013717412948608398, 0.0041152238845825195, -0.00045837944195925573, 0.0
013753175735478074}, |
451 {-2.1033774145221198, -1.4046019261273715e-008, -0.70062688352066704, -1.270
6324683777995e-008}, | 398 {-2.1033774145221198, -1.4046019261273715e-008, -0.70062688352066704, -1.270
6324683777995e-008}, |
452 }; | 399 }; |
453 | 400 |
454 /*DEF_TEST(PathOpsAngleFindSlop, reporter) { | 401 DEF_TEST(PathOpsAngleFindSlop, reporter) { |
455 for (size_t index = 0; index < SK_ARRAY_COUNT(slopTests); ++index) { | 402 if (gDisableAngleTests) { |
| 403 return; |
| 404 } |
| 405 for (int index = 0; index < (int) SK_ARRAY_COUNT(slopTests); ++index) { |
456 const double* slopTest = slopTests[index]; | 406 const double* slopTest = slopTests[index]; |
457 double x = slopTest[0]; | 407 double x = slopTest[0]; |
458 double y = slopTest[1]; | 408 double y = slopTest[1]; |
459 double rx = slopTest[2]; | 409 double rx = slopTest[2]; |
460 double ry = slopTest[3]; | 410 double ry = slopTest[3]; |
461 SkDebugf("%s xy %d=%d\n", __FUNCTION__, (int) index, find_slop(x, y, rx
, ry)); | 411 SkDebugf("%s xy %d=%d\n", __FUNCTION__, index, find_slop(x, y, rx, ry))
; |
462 SkDebugf("%s rxy %d=%d\n", __FUNCTION__, (int) index, find_slop(rx, ry,
x, y)); | 412 SkDebugf("%s rxy %d=%d\n", __FUNCTION__, index, find_slop(rx, ry, x, y))
; |
463 double angle = diamond_angle(y, x); | 413 double angle = diamond_angle(y, x); |
464 double rAngle = diamond_angle(ry, rx); | 414 double rAngle = diamond_angle(ry, rx); |
465 double diff = fabs(angle - rAngle); | 415 double diff = fabs(angle - rAngle); |
466 SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCT
ION__, | 416 SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCT
ION__, |
467 angle, rAngle, diff, (int) (diff / FLT_EPSILON)); | 417 angle, rAngle, diff, (int) (diff / FLT_EPSILON)); |
468 | 418 } |
469 } | 419 } |
470 }*/ | 420 |
471 #endif | 421 class PathOpsAngleTester { |
| 422 public: |
| 423 static int After(const SkOpAngle& lh, const SkOpAngle& rh) { |
| 424 return lh.after(&rh); |
| 425 } |
| 426 |
| 427 static int ConvexHullOverlaps(const SkOpAngle& lh, const SkOpAngle& rh) { |
| 428 return lh.convexHullOverlaps(rh); |
| 429 } |
| 430 |
| 431 static int Orderable(const SkOpAngle& lh, const SkOpAngle& rh) { |
| 432 return lh.orderable(rh); |
| 433 } |
| 434 |
| 435 static int EndsIntersect(const SkOpAngle& lh, const SkOpAngle& rh) { |
| 436 return lh.endsIntersect(rh); |
| 437 } |
| 438 |
| 439 static void SetNext(SkOpAngle& lh, SkOpAngle& rh) { |
| 440 lh.fNext = &rh; |
| 441 } |
| 442 }; |
| 443 |
| 444 class PathOpsSegmentTester { |
| 445 public: |
| 446 static void ConstructCubic(SkOpSegment* segment, SkPoint shortCubic[4]) { |
| 447 segment->debugConstructCubic(shortCubic); |
| 448 } |
| 449 |
| 450 static void ConstructLine(SkOpSegment* segment, SkPoint shortLine[2]) { |
| 451 segment->debugConstructLine(shortLine); |
| 452 } |
| 453 |
| 454 static void ConstructQuad(SkOpSegment* segment, SkPoint shortQuad[3]) { |
| 455 segment->debugConstructQuad(shortQuad); |
| 456 } |
| 457 |
| 458 static void DebugReset(SkOpSegment* segment) { |
| 459 segment->debugReset(); |
| 460 } |
| 461 }; |
| 462 |
| 463 struct CircleData { |
| 464 const SkDCubic fPts; |
| 465 const int fPtCount; |
| 466 SkPoint fShortPts[4]; |
| 467 }; |
| 468 |
| 469 static CircleData circleDataSet[] = { |
| 470 { {{{313.0155029296875, 207.90290832519531}, {320.05078125, 227.587432861328
12}}}, 2, {} }, |
| 471 { {{{313.0155029296875, 207.90290832519531}, {313.98246891063195, 219.336152
03830394}, |
| 472 {320.05078125, 227.58743286132812}}}, 3, {} }, |
| 473 }; |
| 474 |
| 475 static const int circleDataSetSize = (int) SK_ARRAY_COUNT(circleDataSet); |
| 476 |
| 477 DEF_TEST(PathOpsAngleCircle, reporter) { |
| 478 SkOpSegment segment[2]; |
| 479 for (int index = 0; index < circleDataSetSize; ++index) { |
| 480 CircleData& data = circleDataSet[index]; |
| 481 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) { |
| 482 data.fShortPts[idx2] = data.fPts.fPts[idx2].asSkPoint(); |
| 483 } |
| 484 switch (data.fPtCount) { |
| 485 case 2: |
| 486 PathOpsSegmentTester::ConstructLine(&segment[index], data.fShort
Pts); |
| 487 break; |
| 488 case 3: |
| 489 PathOpsSegmentTester::ConstructQuad(&segment[index], data.fShort
Pts); |
| 490 break; |
| 491 case 4: |
| 492 PathOpsSegmentTester::ConstructCubic(&segment[index], data.fShor
tPts); |
| 493 break; |
| 494 } |
| 495 } |
| 496 PathOpsAngleTester::Orderable(segment[0].angle(0), segment[1].angle(0)); |
| 497 } |
| 498 |
| 499 struct IntersectData { |
| 500 const SkDCubic fPts; |
| 501 const int fPtCount; |
| 502 double fTStart; |
| 503 double fTEnd; |
| 504 SkPoint fShortPts[4]; |
| 505 }; |
| 506 |
| 507 static IntersectData intersectDataSet1[] = { |
| 508 { {{{322.935669,231.030273}, {312.832214,220.393295}, {312.832214,203.454178
}}}, 3, |
| 509 0.865309956, 0.154740299, {} }, |
| 510 { {{{322.12738,233.397751}, {295.718353,159.505829}}}, 2, |
| 511 0.345028807, 0.0786326511, {} }, |
| 512 { {{{322.935669,231.030273}, {312.832214,220.393295}, {312.832214,203.454178
}}}, 3, |
| 513 0.865309956, 1, {} }, |
| 514 { {{{322.12738,233.397751}, {295.718353,159.505829}}}, 2, |
| 515 0.345028807, 1, {} }, |
| 516 }; |
| 517 |
| 518 static IntersectData intersectDataSet2[] = { |
| 519 { {{{364.390686,157.898193}, {375.281769,136.674606}, {396.039917,136.674606
}}}, 3, |
| 520 0.578520747, 1, {} }, |
| 521 { {{{364.390686,157.898193}, {375.281769,136.674606}, {396.039917,136.674606
}}}, 3, |
| 522 0.578520747, 0.536512973, {} }, |
| 523 { {{{366.608826,151.196014}, {378.803101,136.674606}, {398.164948,136.674606
}}}, 3, |
| 524 0.490456543, 1, {} }, |
| 525 }; |
| 526 |
| 527 static IntersectData intersectDataSet3[] = { |
| 528 { {{{2.000000,0.000000}, {1.33333333,0.66666667}}}, 2, 1, 0, {} }, |
| 529 { {{{1.33333333,0.66666667}, {0.000000,2.000000}}}, 2, 0, 0.25, {} }, |
| 530 { {{{2.000000,2.000000}, {1.33333333,0.66666667}}}, 2, 1, 0, {} }, |
| 531 }; |
| 532 |
| 533 static IntersectData intersectDataSet4[] = { |
| 534 { {{{1.3333333,0.6666667}, {0.000,2.000}}}, 2, 0.250000006, 0, {} }, |
| 535 { {{{1.000,0.000}, {1.000,1.000}}}, 2, 1, 0, {} }, |
| 536 { {{{1.000,1.000}, {0.000,0.000}}}, 2, 0, 1, {} }, |
| 537 }; |
| 538 |
| 539 static IntersectData intersectDataSet5[] = { |
| 540 { {{{0.000,0.000}, {1.000,0.000}, {1.000,1.000}}}, 3, 1, 0.666666667, {} }, |
| 541 { {{{0.000,0.000}, {2.000,1.000}, {0.000,2.000}}}, 3, 0.5, 1, {} }, |
| 542 { {{{0.000,0.000}, {2.000,1.000}, {0.000,2.000}}}, 3, 0.5, 0, {} }, |
| 543 }; |
| 544 |
| 545 static IntersectData intersectDataSet6[] = { // pathops_visualizer.htm:3658 |
| 546 { {{{0.000,1.000}, {3.000,4.000}, {1.000,0.000}, {3.000,0.000}}}, 4, 0.09253
39054, 0, {} }, // pathops_visualizer.htm:3616 |
| 547 { {{{0.000,1.000}, {0.000,3.000}, {1.000,0.000}, {4.000,3.000}}}, 4, 0.45387
2386, 0, {} }, // pathops_visualizer.htm:3616 |
| 548 { {{{0.000,1.000}, {3.000,4.000}, {1.000,0.000}, {3.000,0.000}}}, 4, 0.09253
39054, 0.417096368, {} }, // pathops_visualizer.htm:3616 |
| 549 }; |
| 550 |
| 551 static IntersectData intersectDataSet7[] = { // pathops_visualizer.htm:3748 |
| 552 { {{{2.000,1.000}, {0.000,1.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.h
tm:3706 |
| 553 { {{{2.000,0.000}, {0.000,2.000}}}, 2, 0.5, 1, {} }, // pathops_visualizer.h
tm:3706 |
| 554 { {{{0.000,1.000}, {0.000,2.000}, {2.000,0.000}, {2.000,1.000}}}, 4, 0.5, 1,
{} }, // pathops_visualizer.htm:3706 |
| 555 }; // |
| 556 |
| 557 static IntersectData intersectDataSet8[] = { // pathops_visualizer.htm:4194 |
| 558 { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.31100
7457, 0.285714286, {} }, // pathops_visualizer.htm:4152 |
| 559 { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.58988
5081, 0.999982974, {} }, // pathops_visualizer.htm:4152 |
| 560 { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.58988
5081, 0.576935809, {} }, // pathops_visualizer.htm:4152 |
| 561 }; // |
| 562 |
| 563 static IntersectData intersectDataSet9[] = { // pathops_visualizer.htm:4142 |
| 564 { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.47662
7072, 0.311007457, {} }, // pathops_visualizer.htm:4100 |
| 565 { {{{1.000,5.000}, {3.000,4.000}, {1.000,0.000}, {3.000,2.000}}}, 4, 0.99998
2974, 1, {} }, // pathops_visualizer.htm:4100 |
| 566 { {{{0.000,1.000}, {2.000,3.000}, {5.000,1.000}, {4.000,3.000}}}, 4, 0.47662
7072, 1, {} }, // pathops_visualizer.htm:4100 |
| 567 }; // |
| 568 |
| 569 static IntersectData intersectDataSet10[] = { // pathops_visualizer.htm:4186 |
| 570 { {{{0.000,1.000}, {1.000,6.000}, {1.000,0.000}, {1.000,0.000}}}, 4, 0.78819
5121, 0.726275769, {} }, // pathops_visualizer.htm:4144 |
| 571 { {{{0.000,1.000}, {0.000,1.000}, {1.000,0.000}, {6.000,1.000}}}, 4, 0.47337
8977, 1, {} }, // pathops_visualizer.htm:4144 |
| 572 { {{{0.000,1.000}, {1.000,6.000}, {1.000,0.000}, {1.000,0.000}}}, 4, 0.78819
5121, 1, {} }, // pathops_visualizer.htm:4144 |
| 573 }; // |
| 574 |
| 575 static IntersectData intersectDataSet11[] = { // pathops_visualizer.htm:4704 |
| 576 { {{{979.305,561.000}, {1036.695,291.000}}}, 2, 0.888888874, 0.11111108, {}
}, // pathops_visualizer.htm:4662 |
| 577 { {{{1006.695,291.000}, {1023.264,291.000}, {1033.840,304.431}, {1030.318,32
1.000}}}, 4, 1, 0, {} }, // pathops_visualizer.htm:4662 |
| 578 { {{{979.305,561.000}, {1036.695,291.000}}}, 2, 0.888888874, 1, {} }, // pat
hops_visualizer.htm:4662 |
| 579 }; // |
| 580 |
| 581 static IntersectData intersectDataSet12[] = { // pathops_visualizer.htm:5481 |
| 582 { {{{67.000,912.000}, {67.000,913.000}}}, 2, 1, 0, {} }, // pathops_visualiz
er.htm:5439 |
| 583 { {{{67.000,913.000}, {67.000,917.389}, {67.224,921.726}, {67.662,926.000}}}
, 4, 0, 1, {} }, // pathops_visualizer.htm:5439 |
| 584 { {{{194.000,1041.000}, {123.860,1041.000}, {67.000,983.692}, {67.000,913.00
0}}}, 4, 1, 0, {} }, // pathops_visualizer.htm:5439 |
| 585 }; // |
| 586 |
| 587 static IntersectData intersectDataSet13[] = { // pathops_visualizer.htm:5735 |
| 588 { {{{6.000,0.000}, {0.000,4.000}}}, 2, 0.625, 0.25, {} }, // pathops_visuali
zer.htm:5693 |
| 589 { {{{0.000,1.000}, {0.000,6.000}, {4.000,0.000}, {6.000,1.000}}}, 4, 0.5, 0.
833333333, {} }, // pathops_visualizer.htm:5693 |
| 590 { {{{0.000,1.000}, {0.000,6.000}, {4.000,0.000}, {6.000,1.000}}}, 4, 0.5, 0.
379043969, {} }, // pathops_visualizer.htm:5693 |
| 591 }; // |
| 592 |
| 593 static IntersectData intersectDataSet14[] = { // pathops_visualizer.htm:5875 |
| 594 { {{{0.000,1.000}, {4.000,6.000}, {2.000,1.000}, {2.000,0.000}}}, 4, 0.07565
02183, 0.0594570973, {} }, // pathops_visualizer.htm:5833 |
| 595 { {{{1.000,2.000}, {0.000,2.000}, {1.000,0.000}, {6.000,4.000}}}, 4, 0.07565
02184, 0, {} }, // pathops_visualizer.htm:5833 |
| 596 { {{{0.000,1.000}, {4.000,6.000}, {2.000,1.000}, {2.000,0.000}}}, 4, 0.07565
02183, 0.531917258, {} }, // pathops_visualizer.htm:5833 |
| 597 }; // |
| 598 |
| 599 static IntersectData intersectDataSet15[] = { // pathops_visualizer.htm:6580 |
| 600 { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 1, {} }, // path
ops_visualizer.htm:6538 |
| 601 { {{{447.967,894.438}, {448.007,894.424}, {448.014,894.422}}}, 3, 0, 1, {} }
, // pathops_visualizer.htm:6538 |
| 602 { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 0.500000273, {}
}, // pathops_visualizer.htm:6538 |
| 603 }; // |
| 604 |
| 605 static IntersectData intersectDataSet16[] = { // pathops_visualizer.htm:7419 |
| 606 { {{{1.000,4.000}, {4.000,5.000}, {3.000,2.000}, {6.000,3.000}}}, 4, 0.5, 0,
{} }, // pathops_visualizer.htm:7377 |
| 607 { {{{2.000,3.000}, {3.000,6.000}, {4.000,1.000}, {5.000,4.000}}}, 4, 0.5, 0.
112701665, {} }, // pathops_visualizer.htm:7377 |
| 608 { {{{5.000,4.000}, {2.000,3.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.h
tm:7377 |
| 609 }; // |
| 610 |
| 611 #define I(x) intersectDataSet##x |
| 612 |
| 613 static IntersectData* intersectDataSets[] = { |
| 614 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10), |
| 615 I(11), I(12), I(13), I(14), I(15), I(16), |
| 616 }; |
| 617 |
| 618 #undef I |
| 619 #define I(x) (int) SK_ARRAY_COUNT(intersectDataSet##x) |
| 620 |
| 621 static const int intersectDataSetSizes[] = { |
| 622 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10), |
| 623 I(11), I(12), I(13), I(14), I(15), I(16), |
| 624 }; |
| 625 |
| 626 #undef I |
| 627 |
| 628 static const int intersectDataSetsSize = (int) SK_ARRAY_COUNT(intersectDataSetSi
zes); |
| 629 |
| 630 DEF_TEST(PathOpsAngleAfter, reporter) { |
| 631 for (int index = intersectDataSetsSize - 1; index >= 0; --index) { |
| 632 IntersectData* dataArray = intersectDataSets[index]; |
| 633 const int dataSize = intersectDataSetSizes[index]; |
| 634 SkOpSegment segment[3]; |
| 635 for (int index2 = 0; index2 < dataSize - 2; ++index2) { |
| 636 for (int temp = 0; temp < (int) SK_ARRAY_COUNT(segment); ++temp) { |
| 637 PathOpsSegmentTester::DebugReset(&segment[temp]); |
| 638 } |
| 639 for (int index3 = 0; index3 < (int) SK_ARRAY_COUNT(segment); ++index
3) { |
| 640 IntersectData& data = dataArray[index2 + index3]; |
| 641 SkPoint temp[4]; |
| 642 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) { |
| 643 temp[idx2] = data.fPts.fPts[idx2].asSkPoint(); |
| 644 } |
| 645 switch (data.fPtCount) { |
| 646 case 2: { |
| 647 SkDLine seg = SkDLine::SubDivide(temp, data.fTStart, |
| 648 data.fTStart < data.fTEnd ? 1 : 0); |
| 649 data.fShortPts[0] = seg[0].asSkPoint(); |
| 650 data.fShortPts[1] = seg[1].asSkPoint(); |
| 651 PathOpsSegmentTester::ConstructLine(&segment[index3], da
ta.fShortPts); |
| 652 } break; |
| 653 case 3: { |
| 654 SkDQuad seg = SkDQuad::SubDivide(temp, data.fTStart, dat
a.fTEnd); |
| 655 data.fShortPts[0] = seg[0].asSkPoint(); |
| 656 data.fShortPts[1] = seg[1].asSkPoint(); |
| 657 data.fShortPts[2] = seg[2].asSkPoint(); |
| 658 PathOpsSegmentTester::ConstructQuad(&segment[index3], da
ta.fShortPts); |
| 659 } break; |
| 660 case 4: { |
| 661 SkDCubic seg = SkDCubic::SubDivide(temp, data.fTStart, d
ata.fTEnd); |
| 662 data.fShortPts[0] = seg[0].asSkPoint(); |
| 663 data.fShortPts[1] = seg[1].asSkPoint(); |
| 664 data.fShortPts[2] = seg[2].asSkPoint(); |
| 665 data.fShortPts[3] = seg[3].asSkPoint(); |
| 666 PathOpsSegmentTester::ConstructCubic(&segment[index3], d
ata.fShortPts); |
| 667 } break; |
| 668 } |
| 669 } |
| 670 SkOpAngle& angle1 = const_cast<SkOpAngle&>(segment[0].angle(0)); |
| 671 SkOpAngle& angle2 = const_cast<SkOpAngle&>(segment[1].angle(0)); |
| 672 SkOpAngle& angle3 = const_cast<SkOpAngle&>(segment[2].angle(0)); |
| 673 PathOpsAngleTester::SetNext(angle1, angle3); |
| 674 // These data sets are seeded when the set itself fails, so likely the da
taset does not |
| 675 // match the expected result. The tests above return 1 when first added,
but |
| 676 // return 0 after the bug is fixed. |
| 677 SkDEBUGCODE(int result =) PathOpsAngleTester::After(angle2, angle1); |
| 678 SkASSERT(result == 0 || result == 1); |
| 679 } |
| 680 } |
| 681 } |
| 682 |
| 683 void SkOpSegment::debugConstruct() { |
| 684 addStartSpan(1); |
| 685 addEndSpan(1); |
| 686 debugAddAngle(0, 1); |
| 687 } |
| 688 |
| 689 void SkOpSegment::debugAddAngle(int start, int end) { |
| 690 SkASSERT(start != end); |
| 691 SkOpAngle& angle = fAngles.push_back(); |
| 692 angle.set(this, start, end); |
| 693 } |
| 694 |
| 695 void SkOpSegment::debugConstructCubic(SkPoint shortQuad[4]) { |
| 696 addCubic(shortQuad, false, false); |
| 697 addT(NULL, shortQuad[0], 0); |
| 698 addT(NULL, shortQuad[3], 1); |
| 699 debugConstruct(); |
| 700 } |
| 701 |
| 702 void SkOpSegment::debugConstructLine(SkPoint shortQuad[2]) { |
| 703 addLine(shortQuad, false, false); |
| 704 addT(NULL, shortQuad[0], 0); |
| 705 addT(NULL, shortQuad[1], 1); |
| 706 debugConstruct(); |
| 707 } |
| 708 |
| 709 void SkOpSegment::debugConstructQuad(SkPoint shortQuad[3]) { |
| 710 addQuad(shortQuad, false, false); |
| 711 addT(NULL, shortQuad[0], 0); |
| 712 addT(NULL, shortQuad[2], 1); |
| 713 debugConstruct(); |
| 714 } |
OLD | NEW |