diff options
-rw-r--r-- | src/gpu/GrShape.cpp | 5 | ||||
-rw-r--r-- | src/gpu/GrShape.h | 4 | ||||
-rw-r--r-- | tests/GrShapeTest.cpp | 57 |
3 files changed, 60 insertions, 6 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp index 9636427c8e..91cd3c8eb1 100644 --- a/src/gpu/GrShape.cpp +++ b/src/gpu/GrShape.cpp @@ -386,7 +386,6 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { scale)) { tmpParent.init(*srcForPathEffect, GrStyle(strokeRec, nullptr)); *this = tmpParent.get()->applyStyle(apply, scale); - fOriginalPath = parent.fOriginalPath; return; } // A path effect has access to change the res scale but we aren't expecting it to and it @@ -498,6 +497,10 @@ void GrShape::attemptToSimplifyPath() { } if (Type::kPath != fType) { fInheritedKey.reset(0); + // Whenever we simplify to a non-path, break the chain so we no longer refer to the + // original path. This prevents attaching genID listeners to temporary paths created when + // drawing simple shapes. + fOriginalPath.reset(); if (Type::kRRect == fType) { this->attemptToSimplifyRRect(); } else if (Type::kLine == fType) { diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h index dd8aa850d6..032c4d5e57 100644 --- a/src/gpu/GrShape.h +++ b/src/gpu/GrShape.h @@ -373,9 +373,11 @@ public: void addGenIDChangeListener(SkPathRef::GenIDChangeListener* listener) const; /** - * Gets the generation ID of the *original* path. This is only exposed for unit tests. + * Helpers that are only exposed for unit tests, to determine if the shape is a path, and get + * the generation ID of the *original* path. */ uint32_t testingOnly_getOriginalGenerationID() const; + bool testingOnly_isPath() const; private: diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp index 2b2a169477..259026c8d0 100644 --- a/tests/GrShapeTest.cpp +++ b/tests/GrShapeTest.cpp @@ -21,6 +21,10 @@ uint32_t GrShape::testingOnly_getOriginalGenerationID() const { return fOriginalPath.getGenerationID(); } +bool GrShape::testingOnly_isPath() const { + return Type::kPath == fType; +} + using Key = SkTArray<uint32_t>; static bool make_key(Key* key, const GrShape& shape) { @@ -213,6 +217,54 @@ static void check_equivalence(skiatest::Reporter* r, const GrShape& a, const GrS REPORTER_ASSERT(r, ignoreInversenessDifference || a.inverseFilled() == b.inverseFilled()); } +static void check_original_path_ids(skiatest::Reporter* r, const GrShape& base, const GrShape& pe, + const GrShape& peStroke, const GrShape& full) { + bool baseIsPath = base.testingOnly_isPath(); + bool peIsPath = pe.testingOnly_isPath(); + bool peStrokeIsPath = peStroke.testingOnly_isPath(); + bool fullIsPath = full.testingOnly_isPath(); + + REPORTER_ASSERT(r, peStrokeIsPath == fullIsPath); + + uint32_t baseID = base.testingOnly_getOriginalGenerationID(); + uint32_t peID = pe.testingOnly_getOriginalGenerationID(); + uint32_t peStrokeID = peStroke.testingOnly_getOriginalGenerationID(); + uint32_t fullID = full.testingOnly_getOriginalGenerationID(); + + // All empty paths have the same gen ID + uint32_t emptyID = SkPath().getGenerationID(); + + // If we started with a real path, then our genID should match that path's gen ID (and not be + // empty). If we started with a simple shape, our original path should have been reset. + REPORTER_ASSERT(r, baseIsPath == (baseID != emptyID)); + + // For the derived shapes, if they're simple types, their original paths should have been reset + REPORTER_ASSERT(r, peIsPath || (peID == emptyID)); + REPORTER_ASSERT(r, peStrokeIsPath || (peStrokeID == emptyID)); + REPORTER_ASSERT(r, fullIsPath || (fullID == emptyID)); + + if (!peIsPath) { + // If the path effect produces a simple shape, then there are no unbroken chains to test + return; + } + + // From here on, we know that the path effect produced a shape that was a "real" path + + if (baseIsPath) { + REPORTER_ASSERT(r, baseID == peID); + } + + if (peStrokeIsPath) { + REPORTER_ASSERT(r, peID == peStrokeID); + REPORTER_ASSERT(r, peStrokeID == fullID); + } + + if (baseIsPath && peStrokeIsPath) { + REPORTER_ASSERT(r, baseID == peStrokeID); + REPORTER_ASSERT(r, baseID == fullID); + } +} + void test_inversions(skiatest::Reporter* r, const GrShape& shape, const Key& shapeKey) { GrShape preserve = GrShape::MakeFilled(shape, GrShape::FillInversion::kPreserve); Key preserveKey; @@ -499,10 +551,7 @@ private: // All shapes should report the same "original" path, so that path renderers can get to it // if necessary. - uint32_t baseGenID = fBase.testingOnly_getOriginalGenerationID(); - REPORTER_ASSERT(r, baseGenID == fAppliedPE.testingOnly_getOriginalGenerationID()); - REPORTER_ASSERT(r, baseGenID == fAppliedPEThenStroke.testingOnly_getOriginalGenerationID()); - REPORTER_ASSERT(r, baseGenID == fAppliedFull.testingOnly_getOriginalGenerationID()); + check_original_path_ids(r, fBase, fAppliedPE, fAppliedPEThenStroke, fAppliedFull); // Applying the path effect and then the stroke should always be the same as applying // both in one go. |