Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 | 7 |
| 8 #include <initializer_list> | 8 #include <initializer_list> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include "Test.h" | 10 #include "Test.h" |
| 11 #if SK_SUPPORT_GPU | 11 #if SK_SUPPORT_GPU |
| 12 #include "GrShape.h" | 12 #include "GrShape.h" |
| 13 #include "SkCanvas.h" | |
| 14 #include "SkDashPathEffect.h" | |
| 13 #include "SkPath.h" | 15 #include "SkPath.h" |
| 14 #include "SkDashPathEffect.h" | 16 #include "SkSurface.h" |
| 15 | 17 |
| 16 using Key = SkTArray<uint32_t>; | 18 using Key = SkTArray<uint32_t>; |
| 17 | 19 |
| 18 static bool make_key(Key* key, const GrShape& shape) { | 20 static bool make_key(Key* key, const GrShape& shape) { |
| 19 int size = shape.unstyledKeySize(); | 21 int size = shape.unstyledKeySize(); |
| 20 if (size <= 0) { | 22 if (size <= 0) { |
| 21 key->reset(0); | 23 key->reset(0); |
| 22 return false; | 24 return false; |
| 23 } | 25 } |
| 24 SkASSERT(size); | 26 SkASSERT(size); |
| 25 key->reset(size); | 27 key->reset(size); |
| 26 shape.writeUnstyledKey(key->begin()); | 28 shape.writeUnstyledKey(key->begin()); |
| 27 return true; | 29 return true; |
| 28 } | 30 } |
| 29 | 31 |
| 30 namespace { | 32 namespace { |
| 33 static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds) { | |
| 34 static constexpr int kRes = 2000; | |
| 35 static constexpr int kTol = 1; | |
| 36 GR_STATIC_ASSERT(kRes % 4 == 0); | |
| 37 SkImageInfo info = SkImageInfo::MakeA8(kRes, kRes); | |
| 38 sk_sp<SkSurface> surface = SkSurface::MakeRaster(info); | |
| 39 surface->getCanvas()->clear(0x0); | |
| 40 SkRect clip = SkRect::MakeXYWH(kRes/4, kRes/4, kRes/2, kRes/2); | |
| 41 SkMatrix matrix; | |
| 42 matrix.setRectToRect(bounds, clip, SkMatrix::kFill_ScaleToFit); | |
|
robertphillips
2016/05/12 17:18:47
Is this outset really kosher? If we're going to us
bsalomon
2016/05/12 18:37:58
For the current set of test cases it works at 0 (a
| |
| 43 clip.outset(SkIntToScalar(kTol), SkIntToScalar(kTol)); | |
| 44 surface->getCanvas()->clipRect(clip, SkRegion::kDifference_Op); | |
| 45 surface->getCanvas()->concat(matrix); | |
| 46 SkPaint whitePaint; | |
| 47 whitePaint.setColor(SK_ColorWHITE); | |
| 48 surface->getCanvas()->drawPath(path, whitePaint); | |
| 49 SkPixmap pixmap; | |
| 50 surface->getCanvas()->peekPixels(&pixmap); | |
| 51 static constexpr uint8_t kZeros[kRes] = {0}; | |
| 52 for (int y = 0; y < kRes; ++y) { | |
| 53 const uint8_t* row = pixmap.addr8(0, y); | |
| 54 if (0 != memcmp(kZeros, row, kRes)) { | |
| 55 return false; | |
| 56 } | |
| 57 } | |
| 58 return true; | |
| 59 } | |
| 31 | 60 |
| 32 class TestCase { | 61 class TestCase { |
| 33 public: | 62 public: |
| 34 template <typename GEO> | 63 template <typename GEO> |
| 35 TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r, | 64 TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r, |
| 36 SkScalar scale = SK_Scalar1) : fBase(geo, paint) { | 65 SkScalar scale = SK_Scalar1) : fBase(geo, paint) { |
| 37 this->init(r, scale); | 66 this->init(r, scale); |
| 38 } | 67 } |
| 39 | 68 |
| 40 struct SelfExpectations { | 69 struct SelfExpectations { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 58 const GrShape& appliedPathEffectShape() const { return fAppliedPE; } | 87 const GrShape& appliedPathEffectShape() const { return fAppliedPE; } |
| 59 const GrShape& appliedFullStyleShape() const { return fAppliedFull; } | 88 const GrShape& appliedFullStyleShape() const { return fAppliedFull; } |
| 60 | 89 |
| 61 // The returned array's count will be 0 if the key shape has no key. | 90 // The returned array's count will be 0 if the key shape has no key. |
| 62 const Key& baseKey() const { return fBaseKey; } | 91 const Key& baseKey() const { return fBaseKey; } |
| 63 const Key& appliedPathEffectKey() const { return fAppliedPEKey; } | 92 const Key& appliedPathEffectKey() const { return fAppliedPEKey; } |
| 64 const Key& appliedFullStyleKey() const { return fAppliedFullKey; } | 93 const Key& appliedFullStyleKey() const { return fAppliedFullKey; } |
| 65 const Key& appliedPathEffectThenStrokeKey() const { return fAppliedPEThenStr okeKey; } | 94 const Key& appliedPathEffectThenStrokeKey() const { return fAppliedPEThenStr okeKey; } |
| 66 | 95 |
| 67 private: | 96 private: |
| 97 static void CheckBounds(skiatest::Reporter* r, const GrShape& shape, const S kRect& bounds) { | |
| 98 SkPath path; | |
| 99 shape.asPath(&path); | |
| 100 // If the bounds are empty, the path ought to be as well. | |
| 101 if (bounds.isEmpty()) { | |
| 102 REPORTER_ASSERT(r, path.isEmpty()); | |
| 103 return; | |
| 104 } | |
| 105 if (path.isEmpty()) { | |
| 106 return; | |
| 107 } | |
| 108 REPORTER_ASSERT(r, test_bounds_by_rasterizing(path, bounds)); | |
| 109 } | |
| 110 | |
| 68 void init(skiatest::Reporter* r, SkScalar scale) { | 111 void init(skiatest::Reporter* r, SkScalar scale) { |
| 69 fAppliedPE = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly, scale); | 112 fAppliedPE = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly, scale); |
| 70 fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffect AndStrokeRec, | 113 fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffect AndStrokeRec, |
| 71 scale); | 114 scale); |
| 72 fAppliedFull = fBase.applyStyle(GrStyle::Apply::kPathEffectAndSt rokeRec, scale); | 115 fAppliedFull = fBase.applyStyle(GrStyle::Apply::kPathEffectAndSt rokeRec, scale); |
| 73 | 116 |
| 74 make_key(&fBaseKey, fBase); | 117 make_key(&fBaseKey, fBase); |
| 75 make_key(&fAppliedPEKey, fAppliedPE); | 118 make_key(&fAppliedPEKey, fAppliedPE); |
| 76 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); | 119 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); |
| 77 make_key(&fAppliedFullKey, fAppliedFull); | 120 make_key(&fAppliedFullKey, fAppliedFull); |
| 78 | 121 |
| 79 // Applying the path effect and then the stroke should always be the sam e as applying | 122 // Applying the path effect and then the stroke should always be the sam e as applying |
| 80 // both in one go. | 123 // both in one go. |
| 81 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); | 124 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); |
| 82 SkPath a, b; | 125 SkPath a, b; |
| 83 fAppliedPEThenStroke.asPath(&a); | 126 fAppliedPEThenStroke.asPath(&a); |
| 84 fAppliedFull.asPath(&b); | 127 fAppliedFull.asPath(&b); |
| 85 REPORTER_ASSERT(r, a == b); | 128 REPORTER_ASSERT(r, a == b); |
| 86 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt y()); | 129 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt y()); |
| 87 | 130 |
| 88 SkPath path; | 131 SkPath path; |
| 89 fBase.asPath(&path); | 132 fBase.asPath(&path); |
| 90 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); | 133 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); |
| 91 fAppliedPE.asPath(&path); | 134 fAppliedPE.asPath(&path); |
| 92 REPORTER_ASSERT(r, path.isEmpty() == fAppliedPE.isEmpty()); | 135 REPORTER_ASSERT(r, path.isEmpty() == fAppliedPE.isEmpty()); |
| 93 fAppliedFull.asPath(&path); | 136 fAppliedFull.asPath(&path); |
| 94 REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty()); | 137 REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty()); |
| 95 | 138 |
| 139 CheckBounds(r, fBase, fBase.bounds()); | |
| 140 CheckBounds(r, fAppliedPE, fAppliedPE.bounds()); | |
| 141 CheckBounds(r, fAppliedPEThenStroke, fAppliedPEThenStroke.bounds()); | |
| 142 CheckBounds(r, fAppliedFull, fAppliedFull.bounds()); | |
| 143 SkRect styledBounds; | |
| 144 fBase.styledBounds(&styledBounds); | |
| 145 CheckBounds(r, fAppliedFull, styledBounds); | |
| 146 fAppliedPE.styledBounds(&styledBounds); | |
| 147 CheckBounds(r, fAppliedFull, styledBounds); | |
| 148 | |
| 96 // Check that the same path is produced when style is applied by GrShape and GrStyle. | 149 // Check that the same path is produced when style is applied by GrShape and GrStyle. |
| 97 SkPath preStyle; | 150 SkPath preStyle; |
| 98 SkPath postPathEffect; | 151 SkPath postPathEffect; |
| 99 SkPath postAllStyle; | 152 SkPath postAllStyle; |
| 100 | 153 |
| 101 fBase.asPath(&preStyle); | 154 fBase.asPath(&preStyle); |
| 102 SkStrokeRec postPEStrokeRec(SkStrokeRec::kFill_InitStyle); | 155 SkStrokeRec postPEStrokeRec(SkStrokeRec::kFill_InitStyle); |
| 103 if (fBase.style().applyPathEffectToPath(&postPathEffect, &postPEStrokeRe c, preStyle, | 156 if (fBase.style().applyPathEffectToPath(&postPathEffect, &postPEStrokeRe c, preStyle, |
| 104 scale)) { | 157 scale)) { |
| 105 // run postPathEffect through GrShape to get any geometry reductions that would have | 158 // run postPathEffect through GrShape to get any geometry reductions that would have |
| (...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 943 } | 996 } |
| 944 } | 997 } |
| 945 | 998 |
| 946 // Test a volatile empty path. | 999 // Test a volatile empty path. |
| 947 test_volatile_path(reporter, SkPath(), true); | 1000 test_volatile_path(reporter, SkPath(), true); |
| 948 | 1001 |
| 949 test_empty_shape(reporter); | 1002 test_empty_shape(reporter); |
| 950 } | 1003 } |
| 951 | 1004 |
| 952 #endif | 1005 #endif |
| OLD | NEW |