PathOpsQuadLineIntersectionThreadedTest.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. #include "include/core/SkString.h"
  8. #include "src/pathops/SkIntersections.h"
  9. #include "src/pathops/SkPathOpsLine.h"
  10. #include "src/pathops/SkPathOpsQuad.h"
  11. #include "src/pathops/SkReduceOrder.h"
  12. #include "tests/PathOpsExtendedTest.h"
  13. #include "tests/PathOpsTestCommon.h"
  14. #include "tests/PathOpsThreadedCommon.h"
  15. #include <utility>
  16. static int doIntersect(SkIntersections& intersections, const SkDQuad& quad, const SkDLine& line,
  17. bool& flipped) {
  18. int result;
  19. flipped = false;
  20. if (line[0].fX == line[1].fX) {
  21. double top = line[0].fY;
  22. double bottom = line[1].fY;
  23. flipped = top > bottom;
  24. if (flipped) {
  25. using std::swap;
  26. swap(top, bottom);
  27. }
  28. result = intersections.vertical(quad, top, bottom, line[0].fX, flipped);
  29. } else if (line[0].fY == line[1].fY) {
  30. double left = line[0].fX;
  31. double right = line[1].fX;
  32. flipped = left > right;
  33. if (flipped) {
  34. using std::swap;
  35. swap(left, right);
  36. }
  37. result = intersections.horizontal(quad, left, right, line[0].fY, flipped);
  38. } else {
  39. intersections.intersect(quad, line);
  40. result = intersections.used();
  41. }
  42. return result;
  43. }
  44. static void testLineIntersect(skiatest::Reporter* reporter, const SkDQuad& quad,
  45. const SkDLine& line, const double x, const double y) {
  46. SkString pathStr;
  47. pathStr.appendf(" path.moveTo(%1.9g, %1.9g);\n", quad[0].fX, quad[0].fY);
  48. pathStr.appendf(" path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n", quad[1].fX,
  49. quad[1].fY, quad[2].fX, quad[2].fY);
  50. pathStr.appendf(" path.moveTo(%1.9g, %1.9g);\n", line[0].fX, line[0].fY);
  51. pathStr.appendf(" path.lineTo(%1.9g, %1.9g);\n", line[1].fX, line[1].fY);
  52. SkIntersections intersections;
  53. bool flipped = false;
  54. int result = doIntersect(intersections, quad, line, flipped);
  55. bool found = false;
  56. for (int index = 0; index < result; ++index) {
  57. double quadT = intersections[0][index];
  58. SkDPoint quadXY = quad.ptAtT(quadT);
  59. double lineT = intersections[1][index];
  60. SkDPoint lineXY = line.ptAtT(lineT);
  61. if (quadXY.approximatelyEqual(lineXY)) {
  62. found = true;
  63. }
  64. }
  65. REPORTER_ASSERT(reporter, found);
  66. }
  67. // find a point on a quad by choosing a t from 0 to 1
  68. // create a vertical span above and below the point
  69. // verify that intersecting the vertical span and the quad returns t
  70. // verify that a vertical span starting at quad[0] intersects at t=0
  71. // verify that a vertical span starting at quad[2] intersects at t=1
  72. static void testQuadLineIntersectMain(PathOpsThreadState* data)
  73. {
  74. PathOpsThreadState& state = *data;
  75. REPORTER_ASSERT(state.fReporter, data);
  76. int ax = state.fA & 0x03;
  77. int ay = state.fA >> 2;
  78. int bx = state.fB & 0x03;
  79. int by = state.fB >> 2;
  80. int cx = state.fC & 0x03;
  81. int cy = state.fC >> 2;
  82. QuadPts q = {{{(double) ax, (double) ay}, {(double) bx, (double) by},
  83. {(double) cx, (double) cy}}};
  84. SkDQuad quad;
  85. quad.debugSet(q.fPts);
  86. SkReduceOrder reducer;
  87. int order = reducer.reduce(quad);
  88. if (order < 3) {
  89. return;
  90. }
  91. for (int tIndex = 0; tIndex <= 4; ++tIndex) {
  92. SkDPoint xy = quad.ptAtT(tIndex / 4.0);
  93. for (int h = -2; h <= 2; ++h) {
  94. for (int v = -2; v <= 2; ++v) {
  95. if (h == v && SkTAbs(h) != 1) {
  96. continue;
  97. }
  98. double x = xy.fX;
  99. double y = xy.fY;
  100. SkDLine line = {{{x - h, y - v}, {x, y}}};
  101. testLineIntersect(state.fReporter, quad, line, x, y);
  102. state.fReporter->bumpTestCount();
  103. SkDLine line2 = {{{x, y}, {x + h, y + v}}};
  104. testLineIntersect(state.fReporter, quad, line2, x, y);
  105. state.fReporter->bumpTestCount();
  106. SkDLine line3 = {{{x - h, y - v}, {x + h, y + v}}};
  107. testLineIntersect(state.fReporter, quad, line3, x, y);
  108. state.fReporter->bumpTestCount();
  109. }
  110. }
  111. }
  112. }
  113. DEF_TEST(PathOpsQuadLineIntersectionThreaded, reporter) {
  114. initializeTests(reporter, "testQuadLineIntersect");
  115. PathOpsThreadedTestRunner testRunner(reporter);
  116. for (int a = 0; a < 16; ++a) {
  117. for (int b = 0 ; b < 16; ++b) {
  118. for (int c = 0 ; c < 16; ++c) {
  119. *testRunner.fRunnables.append() = new PathOpsThreadedRunnable(
  120. &testQuadLineIntersectMain, a, b, c, 0, &testRunner);
  121. }
  122. if (!reporter->allowExtendedTest()) goto finish;
  123. }
  124. }
  125. finish:
  126. testRunner.render();
  127. }