Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: tests/PathOpsAngleTest.cpp

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tests/PathOpsAngleIdeas.cpp ('k') | tests/PathOpsBattles.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkIntersections.h"
9 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 10 #include "SkOpSegment.h"
10 #include "SkPathOpsTriangle.h"
11 #include "SkRandom.h" 11 #include "SkRandom.h"
12 #include "SkTArray.h"
13 #include "SkTSort.h" 12 #include "SkTSort.h"
14 #include "Test.h" 13 #include "Test.h"
15 14
16 static bool gDisableAngleTests = true; 15 static bool gDisableAngleTests = true;
17 16
18 static float next(float f) 17 static float next(float f)
19 { 18 {
20 int fBits = SkFloatAs2sCompliment(f); 19 int fBits = SkFloatAs2sCompliment(f);
21 ++fBits; 20 ++fBits;
22 float fNext = Sk2sComplimentAsFloat(fBits); 21 float fNext = Sk2sComplimentAsFloat(fBits);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 double angle = diamond_angle(y, x); 183 double angle = diamond_angle(y, x);
185 double rAngle = diamond_angle(ry, rx); 184 double rAngle = diamond_angle(ry, rx);
186 double diff = fabs(angle - rAngle); 185 double diff = fabs(angle - rAngle);
187 SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCT ION__, 186 SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCT ION__,
188 angle, rAngle, diff, (int) (diff / FLT_EPSILON)); 187 angle, rAngle, diff, (int) (diff / FLT_EPSILON));
189 } 188 }
190 } 189 }
191 190
192 class PathOpsAngleTester { 191 class PathOpsAngleTester {
193 public: 192 public:
194 static int After(const SkOpAngle& lh, const SkOpAngle& rh) { 193 static int After(SkOpAngle& lh, SkOpAngle& rh) {
195 return lh.after(&rh); 194 return lh.after(&rh);
196 } 195 }
197 196
198 static int ConvexHullOverlaps(const SkOpAngle& lh, const SkOpAngle& rh) { 197 static int ConvexHullOverlaps(SkOpAngle& lh, SkOpAngle& rh) {
199 return lh.convexHullOverlaps(rh); 198 return lh.convexHullOverlaps(&rh);
200 } 199 }
201 200
202 static int Orderable(const SkOpAngle& lh, const SkOpAngle& rh) { 201 static int Orderable(SkOpAngle& lh, SkOpAngle& rh) {
203 return lh.orderable(rh); 202 return lh.orderable(&rh);
204 } 203 }
205 204
206 static int EndsIntersect(const SkOpAngle& lh, const SkOpAngle& rh) { 205 static int EndsIntersect(SkOpAngle& lh, SkOpAngle& rh) {
207 return lh.endsIntersect(rh); 206 return lh.endsIntersect(&rh);
208 } 207 }
209 208
210 static void SetNext(SkOpAngle& lh, SkOpAngle& rh) { 209 static void SetNext(SkOpAngle& lh, SkOpAngle& rh) {
211 lh.fNext = &rh; 210 lh.fNext = &rh;
212 } 211 }
213 }; 212 };
214 213
215 class PathOpsSegmentTester { 214 class PathOpsSegmentTester {
216 public: 215 public:
217 static void ConstructCubic(SkOpSegment* segment, SkPoint shortCubic[4]) {
218 segment->debugConstructCubic(shortCubic);
219 }
220
221 static void ConstructLine(SkOpSegment* segment, SkPoint shortLine[2]) {
222 segment->debugConstructLine(shortLine);
223 }
224
225 static void ConstructQuad(SkOpSegment* segment, SkPoint shortQuad[3]) {
226 segment->debugConstructQuad(shortQuad);
227 }
228
229 static void DebugReset(SkOpSegment* segment) { 216 static void DebugReset(SkOpSegment* segment) {
230 segment->debugReset(); 217 segment->debugReset();
231 } 218 }
232 }; 219 };
233 220
234 struct CircleData { 221 struct CircleData {
235 const SkDCubic fPts; 222 const SkDCubic fPts;
236 const int fPtCount; 223 const int fPtCount;
237 SkPoint fShortPts[4]; 224 SkPoint fShortPts[4];
238 }; 225 };
239 226
240 static CircleData circleDataSet[] = { 227 static CircleData circleDataSet[] = {
241 { {{{313.0155029296875, 207.90290832519531}, {320.05078125, 227.587432861328 12}}}, 2, {} }, 228 { {{{313.0155029296875, 207.90290832519531}, {320.05078125, 227.587432861328 12}}}, 2, {} },
242 { {{{313.0155029296875, 207.90290832519531}, {313.98246891063195, 219.336152 03830394}, 229 { {{{313.0155029296875, 207.90290832519531}, {313.98246891063195, 219.336152 03830394},
243 {320.05078125, 227.58743286132812}}}, 3, {} }, 230 {320.05078125, 227.58743286132812}}}, 3, {} },
244 }; 231 };
245 232
246 static const int circleDataSetSize = (int) SK_ARRAY_COUNT(circleDataSet); 233 static const int circleDataSetSize = (int) SK_ARRAY_COUNT(circleDataSet);
247 234
248 DEF_TEST(PathOpsAngleCircle, reporter) { 235 DEF_TEST(PathOpsAngleCircle, reporter) {
249 SkOpSegment segment[2]; 236 SkChunkAlloc allocator(4096);
237 SkOpContour contour;
238 SkOpGlobalState state(NULL PATH_OPS_DEBUG_PARAMS(&contour));
239 contour.init(&state, false, false);
250 for (int index = 0; index < circleDataSetSize; ++index) { 240 for (int index = 0; index < circleDataSetSize; ++index) {
251 CircleData& data = circleDataSet[index]; 241 CircleData& data = circleDataSet[index];
252 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) { 242 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
253 data.fShortPts[idx2] = data.fPts.fPts[idx2].asSkPoint(); 243 data.fShortPts[idx2] = data.fPts.fPts[idx2].asSkPoint();
254 } 244 }
255 switch (data.fPtCount) { 245 switch (data.fPtCount) {
256 case 2: 246 case 2:
257 PathOpsSegmentTester::ConstructLine(&segment[index], data.fShort Pts); 247 contour.addLine(data.fShortPts, &allocator);
258 break; 248 break;
259 case 3: 249 case 3:
260 PathOpsSegmentTester::ConstructQuad(&segment[index], data.fShort Pts); 250 contour.addQuad(data.fShortPts, &allocator);
261 break; 251 break;
262 case 4: 252 case 4:
263 PathOpsSegmentTester::ConstructCubic(&segment[index], data.fShor tPts); 253 contour.addCubic(data.fShortPts, &allocator);
264 break; 254 break;
265 } 255 }
266 } 256 }
267 PathOpsAngleTester::Orderable(*segment[0].debugLastAngle(), *segment[1].debu gLastAngle()); 257 SkOpSegment* first = contour.first();
258 first->debugAddAngle(0, 1, &allocator);
259 SkOpSegment* next = first->next();
260 next->debugAddAngle(0, 1, &allocator);
261 PathOpsAngleTester::Orderable(*first->debugLastAngle(), *next->debugLastAngl e());
268 } 262 }
269 263
270 struct IntersectData { 264 struct IntersectData {
271 const SkDCubic fPts; 265 const SkDCubic fPts;
272 const int fPtCount; 266 const int fPtCount;
273 double fTStart; 267 double fTStart;
274 double fTEnd; 268 double fTEnd;
275 SkPoint fShortPts[4]; 269 SkPoint fShortPts[4];
276 }; 270 };
277 271
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 { {{{447.967,894.438}, {448.007,894.424}, {448.014,894.422}}}, 3, 0, 1, {} } , // pathops_visualizer.htm:6538 366 { {{{447.967,894.438}, {448.007,894.424}, {448.014,894.422}}}, 3, 0, 1, {} } , // pathops_visualizer.htm:6538
373 { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 0.500000273, {} }, // pathops_visualizer.htm:6538 367 { {{{490.435,879.407}, {405.593,909.436}}}, 2, 0.500554405, 0.500000273, {} }, // pathops_visualizer.htm:6538
374 }; // 368 }; //
375 369
376 static IntersectData intersectDataSet16[] = { // pathops_visualizer.htm:7419 370 static IntersectData intersectDataSet16[] = { // pathops_visualizer.htm:7419
377 { {{{1.000,4.000}, {4.000,5.000}, {3.000,2.000}, {6.000,3.000}}}, 4, 0.5, 0, {} }, // pathops_visualizer.htm:7377 371 { {{{1.000,4.000}, {4.000,5.000}, {3.000,2.000}, {6.000,3.000}}}, 4, 0.5, 0, {} }, // pathops_visualizer.htm:7377
378 { {{{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 372 { {{{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
379 { {{{5.000,4.000}, {2.000,3.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.h tm:7377 373 { {{{5.000,4.000}, {2.000,3.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.h tm:7377
380 }; // 374 }; //
381 375
376 // from skpi_gino_com_16
377 static IntersectData intersectDataSet17[] = {
378 { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
379 , 3, 0.74590454, 0.547660352, {} },
380 { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
381 , 4, 0.12052623, 0, {} },
382 { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
383 , 3, 0.74590454, 1, {} },
384 };
385
386 static IntersectData intersectDataSet18[] = {
387 { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
388 , 3, 0.74590454, 1, {} },
389 { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
390 , 4, 0.12052623, 0.217351928, {} },
391 { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
392 , 3, 0.74590454, 0.547660352, {} },
393 };
394
395 static IntersectData intersectDataSet19[] = {
396 { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
397 , 4, 0.135148995, 0.134791946, {} },
398 { /*seg=3*/ {{{1, 2}, {1, 2.15061641f}, {1, 2.21049166f}, {1.01366711f, 2.21 379328f}}}
399 , 4, 0.956740456, 0.894913214, {} },
400 { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
401 , 4, 0.135148995, 0.551812363, {} },
402 };
403
382 #define I(x) intersectDataSet##x 404 #define I(x) intersectDataSet##x
383 405
384 static IntersectData* intersectDataSets[] = { 406 static IntersectData* intersectDataSets[] = {
385 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10), 407 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
386 I(11), I(12), I(13), I(14), I(15), I(16), 408 I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
387 }; 409 };
388 410
389 #undef I 411 #undef I
390 #define I(x) (int) SK_ARRAY_COUNT(intersectDataSet##x) 412 #define I(x) (int) SK_ARRAY_COUNT(intersectDataSet##x)
391 413
392 static const int intersectDataSetSizes[] = { 414 static const int intersectDataSetSizes[] = {
393 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10), 415 I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
394 I(11), I(12), I(13), I(14), I(15), I(16), 416 I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
395 }; 417 };
396 418
397 #undef I 419 #undef I
398 420
399 static const int intersectDataSetsSize = (int) SK_ARRAY_COUNT(intersectDataSetSi zes); 421 static const int intersectDataSetsSize = (int) SK_ARRAY_COUNT(intersectDataSetSi zes);
400 422
423 struct FourPoints {
424 SkPoint pts[4];
425 };
426
401 DEF_TEST(PathOpsAngleAfter, reporter) { 427 DEF_TEST(PathOpsAngleAfter, reporter) {
428 SkChunkAlloc allocator(4096);
429 SkOpContour contour;
430 SkOpGlobalState state(NULL PATH_OPS_DEBUG_PARAMS(&contour));
431 contour.init(&state, false, false);
402 for (int index = intersectDataSetsSize - 1; index >= 0; --index) { 432 for (int index = intersectDataSetsSize - 1; index >= 0; --index) {
403 IntersectData* dataArray = intersectDataSets[index]; 433 IntersectData* dataArray = intersectDataSets[index];
404 const int dataSize = intersectDataSetSizes[index]; 434 const int dataSize = intersectDataSetSizes[index];
405 SkOpSegment segment[3];
406 for (int index2 = 0; index2 < dataSize - 2; ++index2) { 435 for (int index2 = 0; index2 < dataSize - 2; ++index2) {
407 for (int temp = 0; temp < (int) SK_ARRAY_COUNT(segment); ++temp) { 436 allocator.reset();
408 PathOpsSegmentTester::DebugReset(&segment[temp]); 437 contour.reset();
409 } 438 for (int index3 = 0; index3 < 3; ++index3) {
410 for (int index3 = 0; index3 < (int) SK_ARRAY_COUNT(segment); ++index 3) {
411 IntersectData& data = dataArray[index2 + index3]; 439 IntersectData& data = dataArray[index2 + index3];
412 SkPoint temp[4]; 440 SkPoint* temp = (SkPoint*) SkOpTAllocator<FourPoints>::Allocate( &allocator);
413 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) { 441 for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
414 temp[idx2] = data.fPts.fPts[idx2].asSkPoint(); 442 temp[idx2] = data.fPts.fPts[idx2].asSkPoint();
415 } 443 }
416 switch (data.fPtCount) { 444 switch (data.fPtCount) {
417 case 2: { 445 case 2: {
418 SkDLine seg = SkDLine::SubDivide(temp, data.fTStart, 446 contour.addLine(temp, &allocator);
419 data.fTStart < data.fTEnd ? 1 : 0);
420 data.fShortPts[0] = seg[0].asSkPoint();
421 data.fShortPts[1] = seg[1].asSkPoint();
422 PathOpsSegmentTester::ConstructLine(&segment[index3], da ta.fShortPts);
423 } break; 447 } break;
424 case 3: { 448 case 3: {
425 SkDQuad seg = SkDQuad::SubDivide(temp, data.fTStart, dat a.fTEnd); 449 contour.addQuad(temp, &allocator);
426 data.fShortPts[0] = seg[0].asSkPoint();
427 data.fShortPts[1] = seg[1].asSkPoint();
428 data.fShortPts[2] = seg[2].asSkPoint();
429 PathOpsSegmentTester::ConstructQuad(&segment[index3], da ta.fShortPts);
430 } break; 450 } break;
431 case 4: { 451 case 4: {
432 SkDCubic seg = SkDCubic::SubDivide(temp, data.fTStart, d ata.fTEnd); 452 contour.addCubic(temp, &allocator);
433 data.fShortPts[0] = seg[0].asSkPoint();
434 data.fShortPts[1] = seg[1].asSkPoint();
435 data.fShortPts[2] = seg[2].asSkPoint();
436 data.fShortPts[3] = seg[3].asSkPoint();
437 PathOpsSegmentTester::ConstructCubic(&segment[index3], d ata.fShortPts);
438 } break; 453 } break;
439 } 454 }
440 } 455 }
441 SkOpAngle& angle1 = *const_cast<SkOpAngle*>(segment[0].debugLastAngl e()); 456 SkOpSegment* seg1 = contour.first();
442 SkOpAngle& angle2 = *const_cast<SkOpAngle*>(segment[1].debugLastAngl e()); 457 seg1->debugAddAngle(dataArray[index2 + 0].fTStart, dataArray[index2 + 0].fTEnd, &allocator);
443 SkOpAngle& angle3 = *const_cast<SkOpAngle*>(segment[2].debugLastAngl e()); 458 SkOpSegment* seg2 = seg1->next();
459 seg2->debugAddAngle(dataArray[index2 + 1].fTStart, dataArray[index2 + 1].fTEnd, &allocator);
460 SkOpSegment* seg3 = seg2->next();
461 seg3->debugAddAngle(dataArray[index2 + 2].fTStart, dataArray[index2 + 2].fTEnd, &allocator);
462 SkOpAngle& angle1 = *seg1->debugLastAngle();
463 SkOpAngle& angle2 = *seg2->debugLastAngle();
464 SkOpAngle& angle3 = *seg3->debugLastAngle();
444 PathOpsAngleTester::SetNext(angle1, angle3); 465 PathOpsAngleTester::SetNext(angle1, angle3);
445 // These data sets are seeded when the set itself fails, so likely the da taset does not 466 // These data sets are seeded when the set itself fails, so likely the da taset does not
446 // match the expected result. The tests above return 1 when first added, but 467 // match the expected result. The tests above return 1 when first added, but
447 // return 0 after the bug is fixed. 468 // return 0 after the bug is fixed.
448 SkDEBUGCODE(int result =) PathOpsAngleTester::After(angle2, angle1); 469 SkDEBUGCODE(int result =) PathOpsAngleTester::After(angle2, angle1);
449 SkASSERT(result == 0 || result == 1); 470 SkASSERT(result == 0 || result == 1);
450 } 471 }
451 } 472 }
452 } 473 }
453 474
454 void SkOpSegment::debugConstruct() { 475 void SkOpSegment::debugAddAngle(double startT, double endT, SkChunkAlloc* alloca tor) {
455 addStartSpan(1); 476 SkOpPtT* startPtT = startT == 0 ? fHead.ptT() : startT == 1 ? fTail.ptT()
456 addEndSpan(1); 477 : this->addT(startT, kNoAlias, allocator);
457 debugAddAngle(0, 1); 478 SkOpPtT* endPtT = endT == 0 ? fHead.ptT() : endT == 1 ? fTail.ptT()
479 : this->addT(endT, kNoAlias, allocator);
480 SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
481 SkOpSpanBase* startSpan = &fHead;
482 while (startSpan->ptT() != startPtT) {
483 startSpan = startSpan->upCast()->next();
484 }
485 SkOpSpanBase* endSpan = &fHead;
486 while (endSpan->ptT() != endPtT) {
487 endSpan = endSpan->upCast()->next();
488 }
489 angle->set(startSpan, endSpan);
490 if (startT < endT) {
491 startSpan->upCast()->setToAngle(angle);
492 endSpan->setFromAngle(angle);
493 } else {
494 endSpan->upCast()->setToAngle(angle);
495 startSpan->setFromAngle(angle);
496 }
458 } 497 }
459
460 void SkOpSegment::debugAddAngle(int start, int end) {
461 SkASSERT(start != end);
462 SkOpAngle& angle = fAngles.push_back();
463 angle.set(this, start, end);
464 }
465
466 void SkOpSegment::debugConstructCubic(SkPoint shortQuad[4]) {
467 addCubic(shortQuad, false, false);
468 addT(NULL, shortQuad[0], 0);
469 addT(NULL, shortQuad[3], 1);
470 debugConstruct();
471 }
472
473 void SkOpSegment::debugConstructLine(SkPoint shortQuad[2]) {
474 addLine(shortQuad, false, false);
475 addT(NULL, shortQuad[0], 0);
476 addT(NULL, shortQuad[1], 1);
477 debugConstruct();
478 }
479
480 void SkOpSegment::debugConstructQuad(SkPoint shortQuad[3]) {
481 addQuad(shortQuad, false, false);
482 addT(NULL, shortQuad[0], 0);
483 addT(NULL, shortQuad[2], 1);
484 debugConstruct();
485 }
OLDNEW
« no previous file with comments | « tests/PathOpsAngleIdeas.cpp ('k') | tests/PathOpsBattles.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698