Index: tests/GrShapeTest.cpp |
diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp |
index 138028d738d26d00274552913abc53fd3cda8650..0e83b697d86819af1d9d5af30374fee537fb4876 100644 |
--- a/tests/GrShapeTest.cpp |
+++ b/tests/GrShapeTest.cpp |
@@ -10,8 +10,10 @@ |
#include "Test.h" |
#if SK_SUPPORT_GPU |
#include "GrShape.h" |
-#include "SkPath.h" |
+#include "SkCanvas.h" |
#include "SkDashPathEffect.h" |
+#include "SkPath.h" |
+#include "SkSurface.h" |
using Key = SkTArray<uint32_t>; |
@@ -27,8 +29,44 @@ static bool make_key(Key* key, const GrShape& shape) { |
return true; |
} |
-namespace { |
+static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds) { |
+ static constexpr int kRes = 2000; |
+ // This tolerance is in units of 1/kRes fractions of the bounds width/height. |
+ static constexpr int kTol = 0; |
+ GR_STATIC_ASSERT(kRes % 4 == 0); |
+ SkImageInfo info = SkImageInfo::MakeA8(kRes, kRes); |
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(info); |
+ surface->getCanvas()->clear(0x0); |
+ SkRect clip = SkRect::MakeXYWH(kRes/4, kRes/4, kRes/2, kRes/2); |
+ SkMatrix matrix; |
+ matrix.setRectToRect(bounds, clip, SkMatrix::kFill_ScaleToFit); |
+ clip.outset(SkIntToScalar(kTol), SkIntToScalar(kTol)); |
+ surface->getCanvas()->clipRect(clip, SkRegion::kDifference_Op); |
+ surface->getCanvas()->concat(matrix); |
+ SkPaint whitePaint; |
+ whitePaint.setColor(SK_ColorWHITE); |
+ surface->getCanvas()->drawPath(path, whitePaint); |
+ SkPixmap pixmap; |
+ surface->getCanvas()->peekPixels(&pixmap); |
+#if defined(SK_BUILD_FOR_WIN) |
+ // The static constexpr version in #else causes cl.exe to crash. |
+ const uint8_t* kZeros = reinterpret_cast<uint8_t*>(calloc(kRes, 1)); |
+#else |
+ static constexpr uint8_t kZeros[kRes] = {0}; |
+#endif |
+ for (int y = 0; y < kRes/4; ++y) { |
+ const uint8_t* row = pixmap.addr8(0, y); |
+ if (0 != memcmp(kZeros, row, kRes)) { |
+ return false; |
+ } |
+ } |
+#ifdef SK_BUILD_FOR_WIN |
+ free(const_cast<uint8_t*>(kZeros)); |
+#endif |
+ return true; |
+} |
+namespace { |
class TestCase { |
public: |
template <typename GEO> |
@@ -65,6 +103,20 @@ public: |
const Key& appliedPathEffectThenStrokeKey() const { return fAppliedPEThenStrokeKey; } |
private: |
+ static void CheckBounds(skiatest::Reporter* r, const GrShape& shape, const SkRect& bounds) { |
+ SkPath path; |
+ shape.asPath(&path); |
+ // If the bounds are empty, the path ought to be as well. |
+ if (bounds.isEmpty()) { |
+ REPORTER_ASSERT(r, path.isEmpty()); |
+ return; |
+ } |
+ if (path.isEmpty()) { |
+ return; |
+ } |
+ REPORTER_ASSERT(r, test_bounds_by_rasterizing(path, bounds)); |
+ } |
+ |
void init(skiatest::Reporter* r, SkScalar scale) { |
fAppliedPE = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly, scale); |
fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, |
@@ -93,6 +145,16 @@ private: |
fAppliedFull.asPath(&path); |
REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty()); |
+ CheckBounds(r, fBase, fBase.bounds()); |
+ CheckBounds(r, fAppliedPE, fAppliedPE.bounds()); |
+ CheckBounds(r, fAppliedPEThenStroke, fAppliedPEThenStroke.bounds()); |
+ CheckBounds(r, fAppliedFull, fAppliedFull.bounds()); |
+ SkRect styledBounds; |
+ fBase.styledBounds(&styledBounds); |
+ CheckBounds(r, fAppliedFull, styledBounds); |
+ fAppliedPE.styledBounds(&styledBounds); |
+ CheckBounds(r, fAppliedFull, styledBounds); |
+ |
// Check that the same path is produced when style is applied by GrShape and GrStyle. |
SkPath preStyle; |
SkPath postPathEffect; |