ClipperTest.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright 2011 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/SkBitmap.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkPaint.h"
  11. #include "include/core/SkPoint.h"
  12. #include "include/core/SkRect.h"
  13. #include "include/core/SkScalar.h"
  14. #include "include/core/SkTypes.h"
  15. #include "src/core/SkEdgeClipper.h"
  16. #include "src/core/SkLineClipper.h"
  17. #include "tests/Test.h"
  18. #include <cstring>
  19. static void test_hairclipping(skiatest::Reporter* reporter) {
  20. SkBitmap bm;
  21. bm.allocN32Pixels(4, 4);
  22. bm.eraseColor(SK_ColorWHITE);
  23. SkPaint paint;
  24. paint.setAntiAlias(true);
  25. SkCanvas canvas(bm);
  26. canvas.clipRect(SkRect::MakeWH(SkIntToScalar(4), SkIntToScalar(2)));
  27. canvas.drawLine(1.5f, 1.5f,
  28. 3.5f, 3.5f, paint);
  29. /**
  30. * We had a bug where we misinterpreted the bottom of the clip, and
  31. * would draw another pixel (to the right in this case) on the same
  32. * last scanline. i.e. we would draw to [2,1], even though this hairline
  33. * should just draw to [1,1], [2,2], [3,3] modulo the clip.
  34. *
  35. * The result of this entire draw should be that we only draw to [1,1]
  36. *
  37. * Fixed in rev. 3366
  38. */
  39. for (int y = 0; y < 4; ++y) {
  40. for (int x = 0; x < 4; ++x) {
  41. bool nonWhite = (1 == y) && (1 == x);
  42. SkPMColor c = *bm.getAddr32(x, y);
  43. if (nonWhite) {
  44. REPORTER_ASSERT(reporter, 0xFFFFFFFF != c);
  45. } else {
  46. REPORTER_ASSERT(reporter, 0xFFFFFFFF == c);
  47. }
  48. }
  49. }
  50. }
  51. static void test_edgeclipper() {
  52. SkEdgeClipper clipper(false);
  53. const SkPoint pts[] = {
  54. { 3.0995476e+010f, 42.929779f },
  55. { -3.0995163e+010f, 51.050385f },
  56. { -3.0995157e+010f, 51.050392f },
  57. { -3.0995134e+010f, 51.050400f },
  58. };
  59. const SkRect clip = { 0, 0, SkIntToScalar(300), SkIntToScalar(200) };
  60. // this should not assert, even though our choppers do a poor numerical
  61. // job when computing their t values.
  62. // http://code.google.com/p/skia/issues/detail?id=444
  63. clipper.clipCubic(pts, clip);
  64. }
  65. static void test_intersectline(skiatest::Reporter* reporter) {
  66. static const SkScalar L = 0;
  67. static const SkScalar T = 0;
  68. static const SkScalar R = SkIntToScalar(100);
  69. static const SkScalar B = SkIntToScalar(100);
  70. static const SkScalar CX = SkScalarHalf(L + R);
  71. static const SkScalar CY = SkScalarHalf(T + B);
  72. static const SkRect gR = { L, T, R, B };
  73. size_t i;
  74. SkPoint dst[2];
  75. static const SkPoint gEmpty[] = {
  76. // sides
  77. { L, CY }, { L - 10, CY },
  78. { R, CY }, { R + 10, CY },
  79. { CX, T }, { CX, T - 10 },
  80. { CX, B }, { CX, B + 10 },
  81. // corners
  82. { L, T }, { L - 10, T - 10 },
  83. { L, B }, { L - 10, B + 10 },
  84. { R, T }, { R + 10, T - 10 },
  85. { R, B }, { R + 10, B + 10 },
  86. };
  87. for (i = 0; i < SK_ARRAY_COUNT(gEmpty); i += 2) {
  88. bool valid = SkLineClipper::IntersectLine(&gEmpty[i], gR, dst);
  89. if (valid) {
  90. SkDebugf("----- [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
  91. }
  92. REPORTER_ASSERT(reporter, !valid);
  93. }
  94. static const SkPoint gFull[] = {
  95. // diagonals, chords
  96. { L, T }, { R, B },
  97. { L, B }, { R, T },
  98. { CX, T }, { CX, B },
  99. { L, CY }, { R, CY },
  100. { CX, T }, { R, CY },
  101. { CX, T }, { L, CY },
  102. { L, CY }, { CX, B },
  103. { R, CY }, { CX, B },
  104. // edges
  105. { L, T }, { L, B },
  106. { R, T }, { R, B },
  107. { L, T }, { R, T },
  108. { L, B }, { R, B },
  109. };
  110. for (i = 0; i < SK_ARRAY_COUNT(gFull); i += 2) {
  111. bool valid = SkLineClipper::IntersectLine(&gFull[i], gR, dst);
  112. if (!valid || memcmp(&gFull[i], dst, sizeof(dst))) {
  113. SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
  114. }
  115. REPORTER_ASSERT(reporter, valid && !memcmp(&gFull[i], dst, sizeof(dst)));
  116. }
  117. static const SkPoint gPartial[] = {
  118. { L - 10, CY }, { CX, CY }, { L, CY }, { CX, CY },
  119. { CX, T - 10 }, { CX, CY }, { CX, T }, { CX, CY },
  120. { R + 10, CY }, { CX, CY }, { R, CY }, { CX, CY },
  121. { CX, B + 10 }, { CX, CY }, { CX, B }, { CX, CY },
  122. // extended edges
  123. { L, T - 10 }, { L, B + 10 }, { L, T }, { L, B },
  124. { R, T - 10 }, { R, B + 10 }, { R, T }, { R, B },
  125. { L - 10, T }, { R + 10, T }, { L, T }, { R, T },
  126. { L - 10, B }, { R + 10, B }, { L, B }, { R, B },
  127. };
  128. for (i = 0; i < SK_ARRAY_COUNT(gPartial); i += 4) {
  129. bool valid = SkLineClipper::IntersectLine(&gPartial[i], gR, dst);
  130. if (!valid || memcmp(&gPartial[i+2], dst, sizeof(dst))) {
  131. SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
  132. }
  133. REPORTER_ASSERT(reporter, valid &&
  134. !memcmp(&gPartial[i+2], dst, sizeof(dst)));
  135. }
  136. }
  137. DEF_TEST(Clipper, reporter) {
  138. test_intersectline(reporter);
  139. test_edgeclipper();
  140. test_hairclipping(reporter);
  141. }
  142. DEF_TEST(LineClipper_skbug_7981, r) {
  143. SkPoint src[] = {{ -5.77698802E+17f, -1.81758057E+23f}, {38127, 2}};
  144. SkPoint dst[2];
  145. SkRect clip = { -32767, -32767, 32767, 32767 };
  146. SkLineClipper::IntersectLine(src, clip, dst);
  147. }