/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <initializer_list>
#include <functional>
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrShape.h"
#include "SkCanvas.h"
#include "SkDashPathEffect.h"
#include "SkPath.h"
#include "SkPathOps.h"
#include "SkSurface.h"
#include "SkClipOpPriv.h"

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) {
    int size = shape.unstyledKeySize();
    if (size <= 0) {
        key->reset(0);
        return false;
    }
    SkASSERT(size);
    key->reset(size);
    shape.writeUnstyledKey(key->begin());
    return true;
}

static bool paths_fill_same(const SkPath& a, const SkPath& b) {
    SkPath pathXor;
    Op(a, b, SkPathOp::kXOR_SkPathOp, &pathXor);
    return pathXor.isEmpty();
}

static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds) {
    // We test the bounds by rasterizing the path into a kRes by kRes grid. The bounds is
    // mapped to the range kRes/4 to 3*kRes/4 in x and y. A difference clip is used to avoid
    // rendering within the bounds (with a tolerance). Then we render the path and check that
    // everything got clipped out.
    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, kDifference_SkClipOp);
    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; ++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;
}

static bool can_interchange_winding_and_even_odd_fill(const GrShape& shape) {
    SkPath path;
    shape.asPath(&path);
    if (shape.style().hasNonDashPathEffect()) {
        return false;
    }
    const SkStrokeRec::Style strokeRecStyle = shape.style().strokeRec().getStyle();
    return strokeRecStyle == SkStrokeRec::kStroke_Style ||
           strokeRecStyle == SkStrokeRec::kHairline_Style ||
           (shape.style().isSimpleFill() && path.isConvex());
}

static void check_equivalence(skiatest::Reporter* r, const GrShape& a, const GrShape& b,
                              const Key& keyA, const Key& keyB) {
    // GrShape only respects the input winding direction and start point for rrect shapes
    // when there is a path effect. Thus, if there are two GrShapes representing the same rrect
    // but one has a path effect in its style and the other doesn't then asPath() and the unstyled
    // key will differ. GrShape will have canonicalized the direction and start point for the shape
    // without the path effect. If *both* have path effects then they should have both preserved
    // the direction and starting point.

    // The asRRect() output params are all initialized just to silence compiler warnings about
    // uninitialized variables.
    SkRRect rrectA = SkRRect::MakeEmpty(), rrectB = SkRRect::MakeEmpty();
    SkPath::Direction dirA = SkPath::kCW_Direction, dirB = SkPath::kCW_Direction;
    unsigned startA = ~0U, startB = ~0U;
    bool invertedA = true, invertedB = true;

    bool aIsRRect = a.asRRect(&rrectA, &dirA, &startA, &invertedA);
    bool bIsRRect = b.asRRect(&rrectB, &dirB, &startB, &invertedB);
    bool aHasPE = a.style().hasPathEffect();
    bool bHasPE = b.style().hasPathEffect();
    bool allowSameRRectButDiffStartAndDir = (aIsRRect && bIsRRect) && (aHasPE != bHasPE);
    // GrShape will close paths with simple fill style.
    bool allowedClosednessDiff = (a.style().isSimpleFill() != b.style().isSimpleFill());
    SkPath pathA, pathB;
    a.asPath(&pathA);
    b.asPath(&pathB);

    // Having a dash path effect can allow 'a' but not 'b' to turn a inverse fill type into a
    // non-inverse fill type  (or vice versa).
    bool ignoreInversenessDifference = false;
    if (pathA.isInverseFillType() != pathB.isInverseFillType()) {
        const GrShape* s1 = pathA.isInverseFillType() ? &a : &b;
        const GrShape* s2 = pathA.isInverseFillType() ? &b : &a;
        bool canDropInverse1 = s1->style().isDashed();
        bool canDropInverse2 = s2->style().isDashed();
        ignoreInversenessDifference = (canDropInverse1 != canDropInverse2);
    }
    bool ignoreWindingVsEvenOdd = false;
    if (SkPath::ConvertToNonInverseFillType(pathA.getFillType()) !=
        SkPath::ConvertToNonInverseFillType(pathB.getFillType())) {
        bool aCanChange = can_interchange_winding_and_even_odd_fill(a);
        bool bCanChange = can_interchange_winding_and_even_odd_fill(b);
        if (aCanChange != bCanChange) {
            ignoreWindingVsEvenOdd = true;
        }
    }
    if (allowSameRRectButDiffStartAndDir) {
        REPORTER_ASSERT(r, rrectA == rrectB);
        REPORTER_ASSERT(r, paths_fill_same(pathA, pathB));
        REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB);
    } else {
        SkPath pA = pathA;
        SkPath pB = pathB;
        REPORTER_ASSERT(r, a.inverseFilled() == pA.isInverseFillType());
        REPORTER_ASSERT(r, b.inverseFilled() == pB.isInverseFillType());
        if (ignoreInversenessDifference) {
            pA.setFillType(SkPath::ConvertToNonInverseFillType(pathA.getFillType()));
            pB.setFillType(SkPath::ConvertToNonInverseFillType(pathB.getFillType()));
        }
        if (ignoreWindingVsEvenOdd) {
            pA.setFillType(pA.isInverseFillType() ? SkPath::kInverseEvenOdd_FillType
                                                  : SkPath::kEvenOdd_FillType);
            pB.setFillType(pB.isInverseFillType() ? SkPath::kInverseEvenOdd_FillType
                                                  : SkPath::kEvenOdd_FillType);
        }
        if (!ignoreInversenessDifference && !ignoreWindingVsEvenOdd) {
            REPORTER_ASSERT(r, keyA == keyB);
        } else {
            REPORTER_ASSERT(r, keyA != keyB);
        }
        if (allowedClosednessDiff) {
            // GrShape will close paths with simple fill style. Make the non-filled path closed
            // so that the comparision will succeed. Make sure both are closed before comparing.
            pA.close();
            pB.close();
        }
        REPORTER_ASSERT(r, pA == pB);
        REPORTER_ASSERT(r, aIsRRect == bIsRRect);
        if (aIsRRect) {
            REPORTER_ASSERT(r, rrectA == rrectB);
            REPORTER_ASSERT(r, dirA == dirB);
            REPORTER_ASSERT(r, startA == startB);
            REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB);
        }
    }
    REPORTER_ASSERT(r, a.isEmpty() == b.isEmpty());
    REPORTER_ASSERT(r, allowedClosednessDiff || a.knownToBeClosed() == b.knownToBeClosed());
    // closedness can affect convexity.
    REPORTER_ASSERT(r, allowedClosednessDiff || a.knownToBeConvex() == b.knownToBeConvex());
    if (a.knownToBeConvex()) {
        REPORTER_ASSERT(r, pathA.isConvex());
    }
    if (b.knownToBeConvex()) {
        REPORTER_ASSERT(r, pathB.isConvex());
    }
    REPORTER_ASSERT(r, a.bounds() == b.bounds());
    REPORTER_ASSERT(r, a.segmentMask() == b.segmentMask());
    // Init these to suppress warnings.
    SkPoint pts[4] {{0, 0,}, {0, 0}, {0, 0}, {0, 0}} ;
    bool invertedLine[2] {true, true};
    REPORTER_ASSERT(r, a.asLine(pts, &invertedLine[0]) == b.asLine(pts + 2, &invertedLine[1]));
    // mayBeInverseFilledAfterStyling() is allowed to differ if one has a arbitrary PE and the other
    // doesn't (since the PE can set any fill type on its output path).
    // Moreover, dash style explicitly ignores inverseness. So if one is dashed but not the other
    // then they may disagree about inverseness.
    if (a.style().hasNonDashPathEffect() == b.style().hasNonDashPathEffect() &&
        a.style().isDashed() == b.style().isDashed()) {
        REPORTER_ASSERT(r, a.mayBeInverseFilledAfterStyling() ==
                           b.mayBeInverseFilledAfterStyling());
    }
    if (a.asLine(nullptr, nullptr)) {
        REPORTER_ASSERT(r, pts[2] == pts[0] && pts[3] == pts[1]);
        REPORTER_ASSERT(r, ignoreInversenessDifference || invertedLine[0] == invertedLine[1]);
        REPORTER_ASSERT(r, invertedLine[0] == a.inverseFilled());
        REPORTER_ASSERT(r, invertedLine[1] == b.inverseFilled());
    }
    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;
    make_key(&preserveKey, preserve);

    GrShape flip = GrShape::MakeFilled(shape, GrShape::FillInversion::kFlip);
    Key flipKey;
    make_key(&flipKey, flip);

    GrShape inverted = GrShape::MakeFilled(shape, GrShape::FillInversion::kForceInverted);
    Key invertedKey;
    make_key(&invertedKey, inverted);

    GrShape noninverted = GrShape::MakeFilled(shape, GrShape::FillInversion::kForceNoninverted);
    Key noninvertedKey;
    make_key(&noninvertedKey, noninverted);

    if (invertedKey.count() || noninvertedKey.count()) {
        REPORTER_ASSERT(r, invertedKey != noninvertedKey);
    }
    if (shape.style().isSimpleFill()) {
        check_equivalence(r, shape, preserve, shapeKey, preserveKey);
    }
    if (shape.inverseFilled()) {
        check_equivalence(r, preserve, inverted, preserveKey, invertedKey);
        check_equivalence(r, flip, noninverted, flipKey, noninvertedKey);
    } else {
        check_equivalence(r, preserve, noninverted, preserveKey, noninvertedKey);
        check_equivalence(r, flip, inverted, flipKey, invertedKey);
    }

    GrShape doubleFlip = GrShape::MakeFilled(flip, GrShape::FillInversion::kFlip);
    Key doubleFlipKey;
    make_key(&doubleFlipKey, doubleFlip);
    // It can be the case that the double flip has no key but preserve does. This happens when the
    // original shape has an inherited style key. That gets dropped on the first inversion flip.
    if (preserveKey.count() && !doubleFlipKey.count()) {
        preserveKey.reset();
    }
    check_equivalence(r, preserve, doubleFlip, preserveKey, doubleFlipKey);
}

namespace {
/**
 * Geo is a factory for creating a GrShape from another representation. It also answers some
 * questions about expected behavior for GrShape given the inputs.
 */
class Geo {
public:
    virtual ~Geo() {}
    virtual GrShape makeShape(const SkPaint&) const = 0;
    virtual SkPath path() const = 0;
    // These functions allow tests to check for special cases where style gets
    // applied by GrShape in its constructor (without calling GrShape::applyStyle).
    // These unfortunately rely on knowing details of GrShape's implementation.
    // These predicates are factored out here to avoid littering the rest of the
    // test code with GrShape implementation details.
    virtual bool fillChangesGeom() const { return false; }
    virtual bool strokeIsConvertedToFill() const { return false; }
    virtual bool strokeAndFillIsConvertedToFill(const SkPaint&) const { return false; }
    // Is this something we expect GrShape to recognize as something simpler than a path.
    virtual bool isNonPath(const SkPaint& paint) const { return true; }
};

class RectGeo : public Geo {
public:
    RectGeo(const SkRect& rect) : fRect(rect) {}

    SkPath path() const override {
        SkPath path;
        path.addRect(fRect);
        return path;
    }

    GrShape makeShape(const SkPaint& paint) const override {
        return GrShape(fRect, paint);
    }

    bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
        SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
        // Converted to an outset rectangle.
        return paint.getStrokeJoin() == SkPaint::kMiter_Join &&
               paint.getStrokeMiter() >= SK_ScalarSqrt2;
    }

private:
    SkRect fRect;
};

class RRectGeo : public Geo {
public:
    RRectGeo(const SkRRect& rrect) : fRRect(rrect) {}

    GrShape makeShape(const SkPaint& paint) const override {
        return GrShape(fRRect, paint);
    }

    SkPath path() const override {
        SkPath path;
        path.addRRect(fRRect);
        return path;
    }

    bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
        SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
        if (fRRect.isRect()) {
            return RectGeo(fRRect.rect()).strokeAndFillIsConvertedToFill(paint);
        }
        return false;
    }

private:
    SkRRect fRRect;
};

class PathGeo : public Geo {
public:
    enum class Invert { kNo, kYes };

    PathGeo(const SkPath& path, Invert invert) : fPath(path)  {
        SkASSERT(!path.isInverseFillType());
        if (Invert::kYes == invert) {
            if (fPath.getFillType() == SkPath::kEvenOdd_FillType) {
                fPath.setFillType(SkPath::kInverseEvenOdd_FillType);
            } else {
                SkASSERT(fPath.getFillType() == SkPath::kWinding_FillType);
                fPath.setFillType(SkPath::kInverseWinding_FillType);
            }
        }
    }

    GrShape makeShape(const SkPaint& paint) const override {
        return GrShape(fPath, paint);
    }

    SkPath path() const override { return fPath; }

    bool fillChangesGeom() const override {
        // unclosed rects get closed. Lines get turned into empty geometry
        return this->isUnclosedRect() || fPath.isLine(nullptr);
    }

    bool strokeIsConvertedToFill() const override {
        return this->isAxisAlignedLine();
    }

    bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
        SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
        if (this->isAxisAlignedLine()) {
            // The fill is ignored (zero area) and the stroke is converted to a rrect.
            return true;
        }
        SkRect rect;
        unsigned start;
        SkPath::Direction dir;
        if (SkPathPriv::IsSimpleClosedRect(fPath, &rect, &dir, &start)) {
            return RectGeo(rect).strokeAndFillIsConvertedToFill(paint);
        }
        return false;
    }

    bool isNonPath(const SkPaint& paint) const override {
        return fPath.isLine(nullptr) || fPath.isEmpty();
    }

private:
    bool isAxisAlignedLine() const {
        SkPoint pts[2];
        if (!fPath.isLine(pts)) {
            return false;
        }
        return pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY;
    }

    bool isUnclosedRect() const {
        bool closed;
        return fPath.isRect(nullptr, &closed, nullptr) && !closed;
    }

    SkPath fPath;
};

class RRectPathGeo : public PathGeo {
public:
    enum class RRectForStroke { kNo, kYes };

    RRectPathGeo(const SkPath& path, const SkRRect& equivalentRRect, RRectForStroke rrectForStroke,
                 Invert invert)
            : PathGeo(path, invert)
            , fRRect(equivalentRRect)
            , fRRectForStroke(rrectForStroke) {}

    RRectPathGeo(const SkPath& path, const SkRect& equivalentRect, RRectForStroke rrectForStroke,
                 Invert invert)
            : RRectPathGeo(path, SkRRect::MakeRect(equivalentRect), rrectForStroke, invert) {}

    bool isNonPath(const SkPaint& paint) const override {
        if (SkPaint::kFill_Style == paint.getStyle() || RRectForStroke::kYes == fRRectForStroke) {
            return true;
        }
        return false;
    }

    const SkRRect& rrect() const { return fRRect; }

private:
    SkRRect         fRRect;
    RRectForStroke  fRRectForStroke;
};

class TestCase {
public:
    TestCase(const Geo& geo, const SkPaint& paint, skiatest::Reporter* r,
             SkScalar scale = SK_Scalar1) : fBase(geo.makeShape(paint)) {
        this->init(r, scale);
    }

    template<typename... ShapeArgs>
    TestCase(skiatest::Reporter* r, ShapeArgs... shapeArgs)
            : fBase(shapeArgs...) {
        this->init(r, SK_Scalar1);
    }

    TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Scalar1)
        : fBase(shape) {
        this->init(r, scale);
    }

    struct SelfExpectations {
        bool fPEHasEffect;
        bool fPEHasValidKey;
        bool fStrokeApplies;
    };

    void testExpectations(skiatest::Reporter* reporter, SelfExpectations expectations) const;

    enum ComparisonExpecation {
        kAllDifferent_ComparisonExpecation,
        kSameUpToPE_ComparisonExpecation,
        kSameUpToStroke_ComparisonExpecation,
        kAllSame_ComparisonExpecation,
    };

    void compare(skiatest::Reporter*, const TestCase& that, ComparisonExpecation) const;

    const GrShape& baseShape() const { return fBase; }
    const GrShape& appliedPathEffectShape() const { return fAppliedPE; }
    const GrShape& appliedFullStyleShape() const { return fAppliedFull; }

    // The returned array's count will be 0 if the key shape has no key.
    const Key& baseKey() const { return fBaseKey; }
    const Key& appliedPathEffectKey() const { return fAppliedPEKey; }
    const Key& appliedFullStyleKey() const { return fAppliedFullKey; }
    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.fLeft > bounds.fRight || bounds.fTop > bounds.fBottom) {
            REPORTER_ASSERT(r, path.isEmpty());
            return;
        }
        if (path.isEmpty()) {
            return;
        }
        // The bounds API explicitly calls out that it does not consider inverseness.
        SkPath p = path;
        p.setFillType(SkPath::ConvertToNonInverseFillType(path.getFillType()));
        REPORTER_ASSERT(r, test_bounds_by_rasterizing(p, bounds));
    }

    void init(skiatest::Reporter* r, SkScalar scale) {
        fAppliedPE           = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly, scale);
        fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
                                                     scale);
        fAppliedFull         = fBase.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, scale);

        make_key(&fBaseKey, fBase);
        make_key(&fAppliedPEKey, fAppliedPE);
        make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke);
        make_key(&fAppliedFullKey, fAppliedFull);

        // All shapes should report the same "original" path, so that path renderers can get to it
        // if necessary.
        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.
        REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey);
        SkPath a, b;
        fAppliedPEThenStroke.asPath(&a);
        fAppliedFull.asPath(&b);
        // If the output of the path effect is a rrect then it is possible for a and b to be
        // different paths that fill identically. The reason is that fAppliedFull will do this:
        // base -> apply path effect -> rrect_as_path -> stroke -> stroked_rrect_as_path
        // fAppliedPEThenStroke will have converted the rrect_as_path back to a rrect. However,
        // now that there is no longer a path effect, the direction and starting index get
        // canonicalized before the stroke.
        if (fAppliedPE.asRRect(nullptr, nullptr, nullptr, nullptr)) {
            REPORTER_ASSERT(r, paths_fill_same(a, b));
        } else {
            REPORTER_ASSERT(r, a == b);
        }
        REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpty());

        SkPath path;
        fBase.asPath(&path);
        REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty());
        REPORTER_ASSERT(r, path.getSegmentMasks() == fBase.segmentMask());
        fAppliedPE.asPath(&path);
        REPORTER_ASSERT(r, path.isEmpty() == fAppliedPE.isEmpty());
        REPORTER_ASSERT(r, path.getSegmentMasks() == fAppliedPE.segmentMask());
        fAppliedFull.asPath(&path);
        REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty());
        REPORTER_ASSERT(r, path.getSegmentMasks() == fAppliedFull.segmentMask());

        CheckBounds(r, fBase, fBase.bounds());
        CheckBounds(r, fAppliedPE, fAppliedPE.bounds());
        CheckBounds(r, fAppliedPEThenStroke, fAppliedPEThenStroke.bounds());
        CheckBounds(r, fAppliedFull, fAppliedFull.bounds());
        SkRect styledBounds = fBase.styledBounds();
        CheckBounds(r, fAppliedFull, styledBounds);
        styledBounds = fAppliedPE.styledBounds();
        CheckBounds(r, fAppliedFull, styledBounds);

        // Check that the same path is produced when style is applied by GrShape and GrStyle.
        SkPath preStyle;
        SkPath postPathEffect;
        SkPath postAllStyle;

        fBase.asPath(&preStyle);
        SkStrokeRec postPEStrokeRec(SkStrokeRec::kFill_InitStyle);
        if (fBase.style().applyPathEffectToPath(&postPathEffect, &postPEStrokeRec, preStyle,
                                                scale)) {
            // run postPathEffect through GrShape to get any geometry reductions that would have
            // occurred to fAppliedPE.
            GrShape(postPathEffect, GrStyle(postPEStrokeRec, nullptr)).asPath(&postPathEffect);

            SkPath testPath;
            fAppliedPE.asPath(&testPath);
            REPORTER_ASSERT(r, testPath == postPathEffect);
            REPORTER_ASSERT(r, postPEStrokeRec.hasEqualEffect(fAppliedPE.style().strokeRec()));
        }
        SkStrokeRec::InitStyle fillOrHairline;
        if (fBase.style().applyToPath(&postAllStyle, &fillOrHairline, preStyle, scale)) {
            SkPath testPath;
            fAppliedFull.asPath(&testPath);
            if (fBase.style().hasPathEffect()) {
                // Because GrShape always does two-stage application when there is a path effect
                // there may be a reduction/canonicalization step between the path effect and
                // strokerec not reflected in postAllStyle since it applied both the path effect
                // and strokerec without analyzing the intermediate path.
                REPORTER_ASSERT(r, paths_fill_same(postAllStyle, testPath));
            } else {
                // Make sure that postAllStyle sees any reductions/canonicalizations that GrShape
                // would apply.
                GrShape(postAllStyle, GrStyle(fillOrHairline)).asPath(&postAllStyle);
                REPORTER_ASSERT(r, testPath == postAllStyle);
            }

            if (fillOrHairline == SkStrokeRec::kFill_InitStyle) {
                REPORTER_ASSERT(r, fAppliedFull.style().isSimpleFill());
            } else {
                REPORTER_ASSERT(r, fAppliedFull.style().isSimpleHairline());
            }
        }
        test_inversions(r, fBase, fBaseKey);
        test_inversions(r, fAppliedPE, fAppliedPEKey);
        test_inversions(r, fAppliedFull, fAppliedFullKey);
    }

    GrShape fBase;
    GrShape fAppliedPE;
    GrShape fAppliedPEThenStroke;
    GrShape fAppliedFull;

    Key fBaseKey;
    Key fAppliedPEKey;
    Key fAppliedPEThenStrokeKey;
    Key fAppliedFullKey;
};

void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations expectations) const {
    // The base's key should always be valid (unless the path is volatile)
    REPORTER_ASSERT(reporter, fBaseKey.count());
    if (expectations.fPEHasEffect) {
        REPORTER_ASSERT(reporter, fBaseKey != fAppliedPEKey);
        REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppliedPEKey.count()));
        REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
        REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppliedFullKey.count()));
        if (expectations.fStrokeApplies && expectations.fPEHasValidKey) {
            REPORTER_ASSERT(reporter, fAppliedPEKey != fAppliedFullKey);
            REPORTER_ASSERT(reporter, SkToBool(fAppliedFullKey.count()));
        }
    } else {
        REPORTER_ASSERT(reporter, fBaseKey == fAppliedPEKey);
        SkPath a, b;
        fBase.asPath(&a);
        fAppliedPE.asPath(&b);
        REPORTER_ASSERT(reporter, a == b);
        if (expectations.fStrokeApplies) {
            REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
        } else {
            REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey);
        }
    }
}

void TestCase::compare(skiatest::Reporter* r, const TestCase& that,
                       ComparisonExpecation expectation) const {
    SkPath a, b;
    switch (expectation) {
        case kAllDifferent_ComparisonExpecation:
            REPORTER_ASSERT(r, fBaseKey != that.fBaseKey);
            REPORTER_ASSERT(r, fAppliedPEKey != that.fAppliedPEKey);
            REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kSameUpToPE_ComparisonExpecation:
            check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey);
            REPORTER_ASSERT(r, fAppliedPEKey != that.fAppliedPEKey);
            REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kSameUpToStroke_ComparisonExpecation:
            check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey);
            check_equivalence(r, fAppliedPE, that.fAppliedPE, fAppliedPEKey, that.fAppliedPEKey);
            REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kAllSame_ComparisonExpecation:
            check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey);
            check_equivalence(r, fAppliedPE, that.fAppliedPE, fAppliedPEKey, that.fAppliedPEKey);
            check_equivalence(r, fAppliedFull, that.fAppliedFull, fAppliedFullKey,
                              that.fAppliedFullKey);
            break;
    }
}
}  // namespace

static sk_sp<SkPathEffect> make_dash() {
    static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f };
    static const SkScalar kPhase = 0.75;
    return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase);
}

static sk_sp<SkPathEffect> make_null_dash() {
    static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0};
    return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals), 0.f);
}

// We make enough TestCases, and they're large enough, that on Google3 builds we exceed
// the maximum stack frame limit.  make_TestCase() moves those temporaries over to the heap.
template <typename... Args>
static std::unique_ptr<TestCase> make_TestCase(Args&&... args) {
    return std::unique_ptr<TestCase>{ new TestCase(std::forward<Args>(args)...) };
}

static void test_basic(skiatest::Reporter* reporter, const Geo& geo) {
    sk_sp<SkPathEffect> dashPE = make_dash();

    TestCase::SelfExpectations expectations;
    SkPaint fill;

    TestCase fillCase(geo, fill, reporter);
    expectations.fPEHasEffect = false;
    expectations.fPEHasValidKey = false;
    expectations.fStrokeApplies = false;
    fillCase.testExpectations(reporter, expectations);
    // Test that another GrShape instance built from the same primitive is the same.
    make_TestCase(geo, fill, reporter)
        ->compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke2RoundBevel;
    stroke2RoundBevel.setStyle(SkPaint::kStroke_Style);
    stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap);
    stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join);
    stroke2RoundBevel.setStrokeWidth(2.f);
    TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = false;
    expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
    stroke2RoundBevelCase.testExpectations(reporter, expectations);
    make_TestCase(geo, stroke2RoundBevel, reporter)
        ->compare(reporter, stroke2RoundBevelCase, TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke2RoundBevelDash = stroke2RoundBevel;
    stroke2RoundBevelDash.setPathEffect(make_dash());
    TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash, reporter);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = true;
    expectations.fStrokeApplies = true;
    stroke2RoundBevelDashCase.testExpectations(reporter, expectations);
    make_TestCase(geo, stroke2RoundBevelDash, reporter)
        ->compare(reporter, stroke2RoundBevelDashCase, TestCase::kAllSame_ComparisonExpecation);

    if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) {
        fillCase.compare(reporter, stroke2RoundBevelCase,
                         TestCase::kAllDifferent_ComparisonExpecation);
        fillCase.compare(reporter, stroke2RoundBevelDashCase,
                         TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        fillCase.compare(reporter, stroke2RoundBevelCase,
                         TestCase::kSameUpToStroke_ComparisonExpecation);
        fillCase.compare(reporter, stroke2RoundBevelDashCase,
                         TestCase::kSameUpToPE_ComparisonExpecation);
    }
    if (geo.strokeIsConvertedToFill()) {
        stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase,
                                      TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase,
                                      TestCase::kSameUpToPE_ComparisonExpecation);
    }

    // Stroke and fill cases
    SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel;
    stroke2RoundBevelAndFill.setStyle(SkPaint::kStrokeAndFill_Style);
    TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporter);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = false;
    expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
    stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations);
    make_TestCase(geo, stroke2RoundBevelAndFill, reporter)->compare(
            reporter, stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash;
    stroke2RoundBevelAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style);
    TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash, reporter);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = false;
    expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
    stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations);
    make_TestCase(geo, stroke2RoundBevelAndFillDash, reporter)->compare(
        reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_ComparisonExpecation);
    stroke2RoundBevelAndFillDashCase.compare(reporter, stroke2RoundBevelAndFillCase,
                                             TestCase::kAllSame_ComparisonExpecation);

    SkPaint hairline;
    hairline.setStyle(SkPaint::kStroke_Style);
    hairline.setStrokeWidth(0.f);
    TestCase hairlineCase(geo, hairline, reporter);
    // Since hairline style doesn't change the SkPath data, it is keyed identically to fill (except
    // in the line and unclosed rect cases).
    if (geo.fillChangesGeom()) {
        hairlineCase.compare(reporter, fillCase, TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
    }
    REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline());
    REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSimpleHairline());
    REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSimpleHairline());

}

static void test_scale(skiatest::Reporter* reporter, const Geo& geo) {
    sk_sp<SkPathEffect> dashPE = make_dash();

    static const SkScalar kS1 = 1.f;
    static const SkScalar kS2 = 2.f;

    SkPaint fill;
    TestCase fillCase1(geo, fill, reporter, kS1);
    TestCase fillCase2(geo, fill, reporter, kS2);
    // Scale doesn't affect fills.
    fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecation);

    SkPaint hairline;
    hairline.setStyle(SkPaint::kStroke_Style);
    hairline.setStrokeWidth(0.f);
    TestCase hairlineCase1(geo, hairline, reporter, kS1);
    TestCase hairlineCase2(geo, hairline, reporter, kS2);
    // Scale doesn't affect hairlines.
    hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(2.f);
    TestCase strokeCase1(geo, stroke, reporter, kS1);
    TestCase strokeCase2(geo, stroke, reporter, kS2);
    // Scale affects the stroke
    if (geo.strokeIsConvertedToFill()) {
        REPORTER_ASSERT(reporter, !strokeCase1.baseShape().style().applies());
        strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_ComparisonExpecation);
    } else {
        strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_ComparisonExpecation);
    }

    SkPaint strokeDash = stroke;
    strokeDash.setPathEffect(make_dash());
    TestCase strokeDashCase1(geo, strokeDash, reporter, kS1);
    TestCase strokeDashCase2(geo, strokeDash, reporter, kS2);
    // Scale affects the dash and the stroke.
    strokeDashCase1.compare(reporter, strokeDashCase2,
                            TestCase::kSameUpToPE_ComparisonExpecation);

    // Stroke and fill cases
    SkPaint strokeAndFill = stroke;
    strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style);
    TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1);
    TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2);
    SkPaint strokeAndFillDash = strokeDash;
    strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style);
    // Dash is ignored for stroke and fill
    TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1);
    TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2);
    // Scale affects the stroke, but check to make sure this didn't become a simpler shape (e.g.
    // stroke-and-filled rect can become a rect), in which case the scale shouldn't matter and the
    // geometries should agree.
    if (geo.strokeAndFillIsConvertedToFill(strokeAndFillDash)) {
        REPORTER_ASSERT(reporter, !strokeAndFillCase1.baseShape().style().applies());
        strokeAndFillCase1.compare(reporter, strokeAndFillCase2,
                                   TestCase::kAllSame_ComparisonExpecation);
        strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2,
                                       TestCase::kAllSame_ComparisonExpecation);
    } else {
        strokeAndFillCase1.compare(reporter, strokeAndFillCase2,
                                   TestCase::kSameUpToStroke_ComparisonExpecation);
    }
    strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1,
                                   TestCase::kAllSame_ComparisonExpecation);
    strokeAndFillDashCase2.compare(reporter, strokeAndFillCase2,
                                   TestCase::kAllSame_ComparisonExpecation);
}

template <typename T>
static void test_stroke_param_impl(skiatest::Reporter* reporter, const Geo& geo,
                                   std::function<void(SkPaint*, T)> setter, T a, T b,
                                   bool paramAffectsStroke,
                                   bool paramAffectsDashAndStroke) {
    // Set the stroke width so that we don't get hairline. However, call the setter afterward so
    // that it can override the stroke width.
    SkPaint strokeA;
    strokeA.setStyle(SkPaint::kStroke_Style);
    strokeA.setStrokeWidth(2.f);
    setter(&strokeA, a);
    SkPaint strokeB;
    strokeB.setStyle(SkPaint::kStroke_Style);
    strokeB.setStrokeWidth(2.f);
    setter(&strokeB, b);

    TestCase strokeACase(geo, strokeA, reporter);
    TestCase strokeBCase(geo, strokeB, reporter);
    if (paramAffectsStroke) {
        // If stroking is immediately incorporated into a geometric transformation then the base
        // shapes will differ.
        if (geo.strokeIsConvertedToFill()) {
            strokeACase.compare(reporter, strokeBCase,
                                TestCase::kAllDifferent_ComparisonExpecation);
        } else {
            strokeACase.compare(reporter, strokeBCase,
                                TestCase::kSameUpToStroke_ComparisonExpecation);
        }
    } else {
        strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_ComparisonExpecation);
    }

    SkPaint strokeAndFillA = strokeA;
    SkPaint strokeAndFillB = strokeB;
    strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style);
    strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style);
    TestCase strokeAndFillACase(geo, strokeAndFillA, reporter);
    TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter);
    if (paramAffectsStroke) {
        // If stroking is immediately incorporated into a geometric transformation then the base
        // shapes will differ.
        if (geo.strokeAndFillIsConvertedToFill(strokeAndFillA) ||
            geo.strokeAndFillIsConvertedToFill(strokeAndFillB)) {
            strokeAndFillACase.compare(reporter, strokeAndFillBCase,
                                       TestCase::kAllDifferent_ComparisonExpecation);
        } else {
            strokeAndFillACase.compare(reporter, strokeAndFillBCase,
                                       TestCase::kSameUpToStroke_ComparisonExpecation);
        }
    } else {
        strokeAndFillACase.compare(reporter, strokeAndFillBCase,
                                   TestCase::kAllSame_ComparisonExpecation);
    }

    // Make sure stroking params don't affect fill style.
    SkPaint fillA = strokeA, fillB = strokeB;
    fillA.setStyle(SkPaint::kFill_Style);
    fillB.setStyle(SkPaint::kFill_Style);
    TestCase fillACase(geo, fillA, reporter);
    TestCase fillBCase(geo, fillB, reporter);
    fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);

    // Make sure just applying the dash but not stroke gives the same key for both stroking
    // variations.
    SkPaint dashA = strokeA, dashB = strokeB;
    dashA.setPathEffect(make_dash());
    dashB.setPathEffect(make_dash());
    TestCase dashACase(geo, dashA, reporter);
    TestCase dashBCase(geo, dashB, reporter);
    if (paramAffectsDashAndStroke) {
        dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
    } else {
        dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpecation);
    }
}

template <typename T>
static void test_stroke_param(skiatest::Reporter* reporter, const Geo& geo,
                              std::function<void(SkPaint*, T)> setter, T a, T b) {
    test_stroke_param_impl(reporter, geo, setter, a, b, true, true);
};

static void test_stroke_cap(skiatest::Reporter* reporter, const Geo& geo) {
    SkPaint hairline;
    hairline.setStrokeWidth(0);
    hairline.setStyle(SkPaint::kStroke_Style);
    GrShape shape = geo.makeShape(hairline);
    // The cap should only affect shapes that may be open.
    bool affectsStroke = !shape.knownToBeClosed();
    // Dashing adds ends that need caps.
    bool affectsDashAndStroke = true;
    test_stroke_param_impl<SkPaint::Cap>(
        reporter,
        geo,
        [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
        SkPaint::kButt_Cap, SkPaint::kRound_Cap,
        affectsStroke,
        affectsDashAndStroke);
};

static bool shape_known_not_to_have_joins(const GrShape& shape) {
    return shape.asLine(nullptr, nullptr) || shape.isEmpty();
}

static void test_stroke_join(skiatest::Reporter* reporter, const Geo& geo) {
    SkPaint hairline;
    hairline.setStrokeWidth(0);
    hairline.setStyle(SkPaint::kStroke_Style);
    GrShape shape = geo.makeShape(hairline);
    // GrShape recognizes certain types don't have joins and will prevent the join type from
    // affecting the style key.
    // Dashing doesn't add additional joins. However, GrShape currently loses track of this
    // after applying the dash.
    bool affectsStroke = !shape_known_not_to_have_joins(shape);
    test_stroke_param_impl<SkPaint::Join>(
            reporter,
            geo,
            [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
            SkPaint::kRound_Join, SkPaint::kBevel_Join,
            affectsStroke, true);
};

static void test_miter_limit(skiatest::Reporter* reporter, const Geo& geo) {
    auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) {
        p->setStrokeJoin(SkPaint::kMiter_Join);
        p->setStrokeMiter(miter);
    };

    auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) {
        p->setStrokeJoin(SkPaint::kRound_Join);
        p->setStrokeMiter(miter);
    };

    SkPaint hairline;
    hairline.setStrokeWidth(0);
    hairline.setStyle(SkPaint::kStroke_Style);
    GrShape shape = geo.makeShape(hairline);
    bool mayHaveJoins = !shape_known_not_to_have_joins(shape);

    // The miter limit should affect stroked and dashed-stroked cases when the join type is
    // miter.
    test_stroke_param_impl<SkScalar>(
        reporter,
        geo,
        setMiterJoinAndLimit,
        0.5f, 0.75f,
        mayHaveJoins,
        true);

    // The miter limit should not affect stroked and dashed-stroked cases when the join type is
    // not miter.
    test_stroke_param_impl<SkScalar>(
        reporter,
        geo,
        setOtherJoinAndLimit,
        0.5f, 0.75f,
        false,
        false);
}

static void test_dash_fill(skiatest::Reporter* reporter, const Geo& geo) {
    // A dash with no stroke should have no effect
    using DashFactoryFn = sk_sp<SkPathEffect>(*)();
    for (DashFactoryFn md : {&make_dash, &make_null_dash}) {
        SkPaint dashFill;
        dashFill.setPathEffect((*md)());
        TestCase dashFillCase(geo, dashFill, reporter);

        TestCase fillCase(geo, SkPaint(), reporter);
        dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
    }
}

void test_null_dash(skiatest::Reporter* reporter, const Geo& geo) {
    SkPaint fill;
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(1.f);
    SkPaint dash;
    dash.setStyle(SkPaint::kStroke_Style);
    dash.setStrokeWidth(1.f);
    dash.setPathEffect(make_dash());
    SkPaint nullDash;
    nullDash.setStyle(SkPaint::kStroke_Style);
    nullDash.setStrokeWidth(1.f);
    nullDash.setPathEffect(make_null_dash());

    TestCase fillCase(geo, fill, reporter);
    TestCase strokeCase(geo, stroke, reporter);
    TestCase dashCase(geo, dash, reporter);
    TestCase nullDashCase(geo, nullDash, reporter);

    // We expect the null dash to be ignored so nullDashCase should match strokeCase, always.
    nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpecation);
    // Check whether the fillCase or strokeCase/nullDashCase would undergo a geometric tranformation
    // on construction in order to determine how to compare the fill and stroke.
    if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) {
        nullDashCase.compare(reporter, fillCase, TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_ComparisonExpecation);
    }
    // In the null dash case we may immediately convert to a fill, but not for the normal dash case.
    if (geo.strokeIsConvertedToFill()) {
        nullDashCase.compare(reporter, dashCase, TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExpecation);
    }
}

void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const Geo& geo) {
    /**
     * This path effect takes any input path and turns it into a rrect. It passes through stroke
     * info.
     */
    class RRectPathEffect : SkPathEffect {
    public:
        static const SkRRect& RRect() {
            static const SkRRect kRRect = SkRRect::MakeRectXY(SkRect::MakeWH(12, 12), 3, 5);
            return kRRect;
        }

        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
                        const SkRect* cullR) const override {
            dst->reset();
            dst->addRRect(RRect());
            return true;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override {
            *dst = RRect().getBounds();
        }
        static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new RRectPathEffect); }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        RRectPathEffect() {}
    };

    SkPaint fill;
    TestCase fillGeoCase(geo, fill, reporter);

    SkPaint pe;
    pe.setPathEffect(RRectPathEffect::Make());
    TestCase geoPECase(geo, pe, reporter);

    SkPaint peStroke;
    peStroke.setPathEffect(RRectPathEffect::Make());
    peStroke.setStrokeWidth(2.f);
    peStroke.setStyle(SkPaint::kStroke_Style);
    TestCase geoPEStrokeCase(geo, peStroke, reporter);

    // Check whether constructing the filled case would cause the base shape to have a different
    // geometry (because of a geometric transformation upon initial GrShape construction).
    if (geo.fillChangesGeom()) {
        fillGeoCase.compare(reporter, geoPECase, TestCase::kAllDifferent_ComparisonExpecation);
        fillGeoCase.compare(reporter, geoPEStrokeCase,
                            TestCase::kAllDifferent_ComparisonExpecation);
    } else {
        fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_ComparisonExpecation);
        fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_ComparisonExpecation);
    }
    geoPECase.compare(reporter, geoPEStrokeCase,
                      TestCase::kSameUpToStroke_ComparisonExpecation);

    TestCase rrectFillCase(reporter, RRectPathEffect::RRect(), fill);
    SkPaint stroke = peStroke;
    stroke.setPathEffect(nullptr);
    TestCase rrectStrokeCase(reporter, RRectPathEffect::RRect(), stroke);

    SkRRect rrect;
    // Applying the path effect should make a SkRRect shape. There is no further stroking in the
    // geoPECase, so the full style should be the same as just the PE.
    REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect, nullptr, nullptr,
                                                                         nullptr));
    REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
    REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.baseKey());

    REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect, nullptr, nullptr,
                                                                        nullptr));
    REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
    REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.baseKey());

    // In the PE+stroke case applying the full style should be the same as just stroking the rrect.
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&rrect, nullptr,
                                                                               nullptr, nullptr));
    REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFillCase.baseKey());

    REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&rrect, nullptr,
                                                                               nullptr, nullptr));
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() ==
                              rrectStrokeCase.appliedFullStyleKey());
}

void test_unknown_path_effect(skiatest::Reporter* reporter, const Geo& geo) {
    /**
     * This path effect just adds two lineTos to the input path.
     */
    class AddLineTosPathEffect : SkPathEffect {
    public:
        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
                        const SkRect* cullR) const override {
            *dst = src;
            // To avoid triggering data-based keying of paths with few verbs we add many segments.
            for (int i = 0; i < 100; ++i) {
                dst->lineTo(SkIntToScalar(i), SkIntToScalar(i));
            }
            return true;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override {
            *dst = src;
            dst->growToInclude({0, 0});
            dst->growToInclude({100, 100});
        }
        static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new AddLineTosPathEffect); }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        AddLineTosPathEffect() {}
    };

     // This path effect should make the keys invalid when it is applied. We only produce a path
     // effect key for dash path effects. So the only way another arbitrary path effect can produce
     // a styled result with a key is to produce a non-path shape that has a purely geometric key.
    SkPaint peStroke;
    peStroke.setPathEffect(AddLineTosPathEffect::Make());
    peStroke.setStrokeWidth(2.f);
    peStroke.setStyle(SkPaint::kStroke_Style);
    TestCase geoPEStrokeCase(geo, peStroke, reporter);
    TestCase::SelfExpectations expectations;
    expectations.fPEHasEffect = true;
    expectations.fPEHasValidKey = false;
    expectations.fStrokeApplies = true;
    geoPEStrokeCase.testExpectations(reporter, expectations);
}

void test_make_hairline_path_effect(skiatest::Reporter* reporter, const Geo& geo) {
    /**
     * This path effect just changes the stroke rec to hairline.
     */
    class MakeHairlinePathEffect : SkPathEffect {
    public:
        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* strokeRec,
                        const SkRect* cullR) const override {
            *dst = src;
            strokeRec->setHairlineStyle();
            return true;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override { *dst = src; }
        static sk_sp<SkPathEffect> Make() {
            return sk_sp<SkPathEffect>(new MakeHairlinePathEffect);
        }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        MakeHairlinePathEffect() {}
    };

    SkPaint fill;
    SkPaint pe;
    pe.setPathEffect(MakeHairlinePathEffect::Make());

    TestCase peCase(geo, pe, reporter);

    SkPath a, b, c;
    peCase.baseShape().asPath(&a);
    peCase.appliedPathEffectShape().asPath(&b);
    peCase.appliedFullStyleShape().asPath(&c);
    if (geo.isNonPath(pe)) {
        // RRect types can have a change in start index or direction after the PE is applied. This
        // is because once the PE is applied, GrShape may canonicalize the dir and index since it
        // is not germane to the styling any longer.
        // Instead we just check that the paths would fill the same both before and after styling.
        REPORTER_ASSERT(reporter, paths_fill_same(a, b));
        REPORTER_ASSERT(reporter, paths_fill_same(a, c));
    } else {
        // The base shape cannot perform canonicalization on the path's fill type because of an
        // unknown path effect. However, after the path effect is applied the resulting hairline
        // shape will canonicalize the path fill type since hairlines (and stroking in general)
        // don't distinguish between even/odd and non-zero winding.
        a.setFillType(b.getFillType());
        REPORTER_ASSERT(reporter, a == b);
        REPORTER_ASSERT(reporter, a == c);
        // If the resulting path is small enough then it will have a key.
        REPORTER_ASSERT(reporter, paths_fill_same(a, b));
        REPORTER_ASSERT(reporter, paths_fill_same(a, c));
        REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey().empty());
        REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey().empty());
    }
    REPORTER_ASSERT(reporter, peCase.appliedPathEffectShape().style().isSimpleHairline());
    REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHairline());
}

void test_volatile_path(skiatest::Reporter* reporter, const Geo& geo) {
    SkPath vPath = geo.path();
    vPath.setIsVolatile(true);

    SkPaint dashAndStroke;
    dashAndStroke.setPathEffect(make_dash());
    dashAndStroke.setStrokeWidth(2.f);
    dashAndStroke.setStyle(SkPaint::kStroke_Style);
    TestCase volatileCase(reporter, vPath, dashAndStroke);
    // We expect a shape made from a volatile path to have a key iff the shape is recognized
    // as a specialized geometry.
    if (geo.isNonPath(dashAndStroke)) {
        REPORTER_ASSERT(reporter, SkToBool(volatileCase.baseKey().count()));
        // In this case all the keys should be identical to the non-volatile case.
        TestCase nonVolatileCase(reporter, geo.path(), dashAndStroke);
        volatileCase.compare(reporter, nonVolatileCase, TestCase::kAllSame_ComparisonExpecation);
    } else {
        // None of the keys should be valid.
        REPORTER_ASSERT(reporter, !SkToBool(volatileCase.baseKey().count()));
        REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectKey().count()));
        REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedFullStyleKey().count()));
        REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectThenStrokeKey().count()));
    }
}

void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const Geo& geo) {
    /**
     * This path effect returns an empty path (possibly inverted)
     */
    class EmptyPathEffect : SkPathEffect {
    public:
        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
                        const SkRect* cullR) const override {
            dst->reset();
            if (fInvert) {
                dst->toggleInverseFillType();
            }
            return true;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override {
            dst->setEmpty();
        }
        static sk_sp<SkPathEffect> Make(bool invert) {
            return sk_sp<SkPathEffect>(new EmptyPathEffect(invert));
        }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        bool fInvert;
        EmptyPathEffect(bool invert) : fInvert(invert) {}
    };

    SkPath emptyPath;
    GrShape emptyShape(emptyPath);
    Key emptyKey;
    make_key(&emptyKey, emptyShape);
    REPORTER_ASSERT(reporter, emptyShape.isEmpty());

    emptyPath.toggleInverseFillType();
    GrShape invertedEmptyShape(emptyPath);
    Key invertedEmptyKey;
    make_key(&invertedEmptyKey, invertedEmptyShape);
    REPORTER_ASSERT(reporter, invertedEmptyShape.isEmpty());

    REPORTER_ASSERT(reporter, invertedEmptyKey != emptyKey);

    SkPaint pe;
    pe.setPathEffect(EmptyPathEffect::Make(false));
    TestCase geoPECase(geo, pe, reporter);
    REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectThenStrokeKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, !geoPECase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, !geoPECase.appliedFullStyleShape().inverseFilled());

    SkPaint peStroke;
    peStroke.setPathEffect(EmptyPathEffect::Make(false));
    peStroke.setStrokeWidth(2.f);
    peStroke.setStyle(SkPaint::kStroke_Style);
    TestCase geoPEStrokeCase(geo, peStroke, reporter);
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectThenStrokeKey() == emptyKey);
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().inverseFilled());
    pe.setPathEffect(EmptyPathEffect::Make(true));

    TestCase geoPEInvertCase(geo, pe, reporter);
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedFullStyleKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedPathEffectKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedPathEffectThenStrokeKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, geoPEInvertCase.appliedFullStyleShape().inverseFilled());

    peStroke.setPathEffect(EmptyPathEffect::Make(true));
    TestCase geoPEInvertStrokeCase(geo, peStroke, reporter);
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedFullStyleKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedPathEffectKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter,
                    geoPEInvertStrokeCase.appliedPathEffectThenStrokeKey() == invertedEmptyKey);
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, geoPEInvertStrokeCase.appliedFullStyleShape().inverseFilled());
}

void test_path_effect_fails(skiatest::Reporter* reporter, const Geo& geo) {
    /**
     * This path effect always fails to apply.
     */
    class FailurePathEffect : SkPathEffect {
    public:
        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
                        const SkRect* cullR) const override {
            return false;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override {
            *dst = src;
        }
        static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new FailurePathEffect); }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        FailurePathEffect() {}
    };

    SkPaint fill;
    TestCase fillCase(geo, fill, reporter);

    SkPaint pe;
    pe.setPathEffect(FailurePathEffect::Make());
    TestCase peCase(geo, pe, reporter);

    SkPaint stroke;
    stroke.setStrokeWidth(2.f);
    stroke.setStyle(SkPaint::kStroke_Style);
    TestCase strokeCase(geo, stroke, reporter);

    SkPaint peStroke = stroke;
    peStroke.setPathEffect(FailurePathEffect::Make());
    TestCase peStrokeCase(geo, peStroke, reporter);

    // In general the path effect failure can cause some of the TestCase::compare() tests to fail
    // for at least two reasons: 1) We will initially treat the shape as unkeyable because of the
    // path effect, but then when the path effect fails we can key it. 2) GrShape will change its
    // mind about whether a unclosed rect is actually rect. The path effect initially bars us from
    // closing it but after the effect fails we can (for the fill+pe case). This causes different
    // routes through GrShape to have equivalent but different representations of the path (closed
    // or not) but that fill the same.
    SkPath a;
    SkPath b;
    fillCase.appliedPathEffectShape().asPath(&a);
    peCase.appliedPathEffectShape().asPath(&b);
    REPORTER_ASSERT(reporter, paths_fill_same(a, b));

    fillCase.appliedFullStyleShape().asPath(&a);
    peCase.appliedFullStyleShape().asPath(&b);
    REPORTER_ASSERT(reporter, paths_fill_same(a, b));

    strokeCase.appliedPathEffectShape().asPath(&a);
    peStrokeCase.appliedPathEffectShape().asPath(&b);
    REPORTER_ASSERT(reporter, paths_fill_same(a, b));

    strokeCase.appliedFullStyleShape().asPath(&a);
    peStrokeCase.appliedFullStyleShape().asPath(&b);
    REPORTER_ASSERT(reporter, paths_fill_same(a, b));
}

DEF_TEST(GrShape_empty_shape, reporter) {
    SkPath emptyPath;
    SkPath invertedEmptyPath;
    invertedEmptyPath.toggleInverseFillType();
    SkPaint fill;
    TestCase fillEmptyCase(reporter, emptyPath, fill);
    REPORTER_ASSERT(reporter, fillEmptyCase.baseShape().isEmpty());
    REPORTER_ASSERT(reporter, fillEmptyCase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, fillEmptyCase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, !fillEmptyCase.baseShape().inverseFilled());
    REPORTER_ASSERT(reporter, !fillEmptyCase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, !fillEmptyCase.appliedFullStyleShape().inverseFilled());
    TestCase fillInvertedEmptyCase(reporter, invertedEmptyPath, fill);
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.baseShape().isEmpty());
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.appliedPathEffectShape().isEmpty());
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.appliedFullStyleShape().isEmpty());
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.baseShape().inverseFilled());
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.appliedPathEffectShape().inverseFilled());
    REPORTER_ASSERT(reporter, fillInvertedEmptyCase.appliedFullStyleShape().inverseFilled());

    Key emptyKey(fillEmptyCase.baseKey());
    REPORTER_ASSERT(reporter, emptyKey.count());
    Key inverseEmptyKey(fillInvertedEmptyCase.baseKey());
    REPORTER_ASSERT(reporter, inverseEmptyKey.count());
    TestCase::SelfExpectations expectations;
    expectations.fStrokeApplies = false;
    expectations.fPEHasEffect = false;
    // This will test whether applying style preserves emptiness
    fillEmptyCase.testExpectations(reporter, expectations);
    fillInvertedEmptyCase.testExpectations(reporter, expectations);

    // Stroking an empty path should have no effect
    SkPaint stroke;
    stroke.setStrokeWidth(2.f);
    stroke.setStyle(SkPaint::kStroke_Style);
    TestCase strokeEmptyCase(reporter, emptyPath, stroke);
    strokeEmptyCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);
    TestCase strokeInvertedEmptyCase(reporter, invertedEmptyPath, stroke);
    strokeInvertedEmptyCase.compare(reporter, fillInvertedEmptyCase,
                                    TestCase::kAllSame_ComparisonExpecation);

    // Dashing and stroking an empty path should have no effect
    SkPaint dashAndStroke;
    dashAndStroke.setPathEffect(make_dash());
    dashAndStroke.setStrokeWidth(2.f);
    dashAndStroke.setStyle(SkPaint::kStroke_Style);
    TestCase dashAndStrokeEmptyCase(reporter, emptyPath, dashAndStroke);
    dashAndStrokeEmptyCase.compare(reporter, fillEmptyCase,
                                   TestCase::kAllSame_ComparisonExpecation);
    TestCase dashAndStrokeInvertexEmptyCase(reporter, invertedEmptyPath, dashAndStroke);
    // Dashing ignores inverseness so this is equivalent to the non-inverted empty fill.
    dashAndStrokeInvertexEmptyCase.compare(reporter, fillEmptyCase,
                                           TestCase::kAllSame_ComparisonExpecation);

    // A shape made from an empty rrect should behave the same as an empty path.
    SkRRect emptyRRect = SkRRect::MakeRect(SkRect::MakeEmpty());
    REPORTER_ASSERT(reporter, emptyRRect.getType() == SkRRect::kEmpty_Type);
    TestCase dashAndStrokeEmptyRRectCase(reporter, emptyRRect, dashAndStroke);
    dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase,
                                        TestCase::kAllSame_ComparisonExpecation);
    static constexpr SkPath::Direction kDir = SkPath::kCCW_Direction;
    static constexpr int kStart = 0;
    TestCase dashAndStrokeEmptyInvertedRRectCase(reporter, emptyRRect, kDir, kStart, true,
                                                 GrStyle(dashAndStroke));
    // Dashing ignores inverseness so this is equivalent to the non-inverted empty fill.
    dashAndStrokeEmptyInvertedRRectCase.compare(reporter, fillEmptyCase,
                                                TestCase::kAllSame_ComparisonExpecation);

    // Same for a rect.
    SkRect emptyRect = SkRect::MakeEmpty();
    TestCase dashAndStrokeEmptyRectCase(reporter, emptyRect, dashAndStroke);
    dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase,
                                       TestCase::kAllSame_ComparisonExpecation);
    TestCase dashAndStrokeEmptyInvertedRectCase(reporter, SkRRect::MakeRect(emptyRect), kDir,
                                                kStart, true, GrStyle(dashAndStroke));
    // Dashing ignores inverseness so this is equivalent to the non-inverted empty fill.
    dashAndStrokeEmptyInvertedRectCase.compare(reporter, fillEmptyCase,
                                               TestCase::kAllSame_ComparisonExpecation);
}

// rect and oval types have rrect start indices that collapse to the same point. Here we select the
// canonical point in these cases.
unsigned canonicalize_rrect_start(int s, const SkRRect& rrect) {
    switch (rrect.getType()) {
        case SkRRect::kRect_Type:
            return (s + 1) & 0b110;
        case SkRRect::kOval_Type:
            return s & 0b110;
        default:
            return s;
    }
}

void test_rrect(skiatest::Reporter* r, const SkRRect& rrect) {
    enum Style {
        kFill,
        kStroke,
        kHairline,
        kStrokeAndFill
    };

    // SkStrokeRec has no default cons., so init with kFill before calling the setters below.
    SkStrokeRec strokeRecs[4] { SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill_InitStyle,
                                SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill_InitStyle};
    strokeRecs[kFill].setFillStyle();
    strokeRecs[kStroke].setStrokeStyle(2.f);
    strokeRecs[kHairline].setHairlineStyle();
    strokeRecs[kStrokeAndFill].setStrokeStyle(3.f, true);
    // Use a bevel join to avoid complications of stroke+filled rects becoming filled rects before
    // applyStyle() is called.
    strokeRecs[kStrokeAndFill].setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBevel_Join, 1.f);
    sk_sp<SkPathEffect> dashEffect = make_dash();

    static constexpr Style kStyleCnt = static_cast<Style>(SK_ARRAY_COUNT(strokeRecs));

    auto index = [](bool inverted,
                    SkPath::Direction dir,
                    unsigned start,
                    Style style,
                    bool dash) -> int {
        return inverted * (2 * 8 * kStyleCnt * 2) +
               dir      * (    8 * kStyleCnt * 2) +
               start    * (        kStyleCnt * 2) +
               style    * (                    2) +
               dash;
    };
    static const SkPath::Direction kSecondDirection = static_cast<SkPath::Direction>(1);
    const int cnt = index(true, kSecondDirection, 7, static_cast<Style>(kStyleCnt - 1), true) + 1;
    SkAutoTArray<GrShape> shapes(cnt);
    for (bool inverted : {false, true}) {
        for (SkPath::Direction dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
            for (unsigned start = 0; start < 8; ++start) {
                for (Style style : {kFill, kStroke, kHairline, kStrokeAndFill}) {
                    for (bool dash : {false, true}) {
                        sk_sp<SkPathEffect> pe = dash ? dashEffect : nullptr;
                        shapes[index(inverted, dir, start, style, dash)] =
                                GrShape(rrect, dir, start, SkToBool(inverted),
                                        GrStyle(strokeRecs[style], std::move(pe)));
                    }
                }
            }
        }
    }

    // Get the keys for some example shape instances that we'll use for comparision against the
    // rest.
    static constexpr SkPath::Direction kExamplesDir = SkPath::kCW_Direction;
    static constexpr unsigned kExamplesStart = 0;
    const GrShape& exampleFillCase = shapes[index(false, kExamplesDir, kExamplesStart, kFill,
                                                  false)];
    Key exampleFillCaseKey;
    make_key(&exampleFillCaseKey, exampleFillCase);

    const GrShape& exampleStrokeAndFillCase = shapes[index(false, kExamplesDir, kExamplesStart,
                                                           kStrokeAndFill, false)];
    Key exampleStrokeAndFillCaseKey;
    make_key(&exampleStrokeAndFillCaseKey, exampleStrokeAndFillCase);

    const GrShape& exampleInvFillCase = shapes[index(true, kExamplesDir, kExamplesStart, kFill,
                                                     false)];
    Key exampleInvFillCaseKey;
    make_key(&exampleInvFillCaseKey, exampleInvFillCase);

    const GrShape& exampleInvStrokeAndFillCase = shapes[index(true, kExamplesDir, kExamplesStart,
                                                              kStrokeAndFill, false)];
    Key exampleInvStrokeAndFillCaseKey;
    make_key(&exampleInvStrokeAndFillCaseKey, exampleInvStrokeAndFillCase);

    const GrShape& exampleStrokeCase = shapes[index(false, kExamplesDir, kExamplesStart, kStroke,
                                                    false)];
    Key exampleStrokeCaseKey;
    make_key(&exampleStrokeCaseKey, exampleStrokeCase);

    const GrShape& exampleInvStrokeCase = shapes[index(true, kExamplesDir, kExamplesStart, kStroke,
                                                       false)];
    Key exampleInvStrokeCaseKey;
    make_key(&exampleInvStrokeCaseKey, exampleInvStrokeCase);

    const GrShape& exampleHairlineCase = shapes[index(false, kExamplesDir, kExamplesStart,
                                                      kHairline, false)];
    Key exampleHairlineCaseKey;
    make_key(&exampleHairlineCaseKey, exampleHairlineCase);

    const GrShape& exampleInvHairlineCase = shapes[index(true, kExamplesDir, kExamplesStart,
                                                         kHairline, false)];
    Key exampleInvHairlineCaseKey;
    make_key(&exampleInvHairlineCaseKey, exampleInvHairlineCase);

    // These are dummy initializations to suppress warnings.
    SkRRect queryRR = SkRRect::MakeEmpty();
    SkPath::Direction queryDir = SkPath::kCW_Direction;
    unsigned queryStart = ~0U;
    bool queryInverted = true;

    REPORTER_ASSERT(r, exampleFillCase.asRRect(&queryRR, &queryDir, &queryStart, &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, !queryInverted);

    REPORTER_ASSERT(r, exampleInvFillCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                  &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, queryInverted);

    REPORTER_ASSERT(r, exampleStrokeAndFillCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                        &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, !queryInverted);

    REPORTER_ASSERT(r, exampleInvStrokeAndFillCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                           &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, queryInverted);

    REPORTER_ASSERT(r, exampleHairlineCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                   &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, !queryInverted);

    REPORTER_ASSERT(r, exampleInvHairlineCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                      &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, queryInverted);

    REPORTER_ASSERT(r, exampleStrokeCase.asRRect(&queryRR, &queryDir, &queryStart, &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, !queryInverted);

    REPORTER_ASSERT(r, exampleInvStrokeCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                    &queryInverted));
    REPORTER_ASSERT(r, queryRR == rrect);
    REPORTER_ASSERT(r, SkPath::kCW_Direction == queryDir);
    REPORTER_ASSERT(r, 0 == queryStart);
    REPORTER_ASSERT(r, queryInverted);

    // Remember that the key reflects the geometry before styling is applied.
    REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvFillCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey == exampleStrokeAndFillCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvStrokeAndFillCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey == exampleStrokeCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvStrokeCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey == exampleHairlineCaseKey);
    REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvHairlineCaseKey);
    REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvFillCaseKey);
    REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvStrokeCaseKey);
    REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvHairlineCaseKey);

    for (bool inverted : {false, true}) {
        for (SkPath::Direction dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
            for (unsigned start = 0; start < 8; ++start) {
                for (bool dash : {false, true}) {
                    const GrShape& fillCase = shapes[index(inverted, dir, start, kFill, dash)];
                    Key fillCaseKey;
                    make_key(&fillCaseKey, fillCase);

                    const GrShape& strokeAndFillCase = shapes[index(inverted, dir, start,
                                                                    kStrokeAndFill, dash)];
                    Key strokeAndFillCaseKey;
                    make_key(&strokeAndFillCaseKey, strokeAndFillCase);

                    // Both fill and stroke-and-fill shapes must respect the inverseness and both
                    // ignore dashing.
                    REPORTER_ASSERT(r, !fillCase.style().pathEffect());
                    REPORTER_ASSERT(r, !strokeAndFillCase.style().pathEffect());
                    TestCase a(fillCase, r);
                    TestCase b(inverted ? exampleInvFillCase : exampleFillCase, r);
                    TestCase c(strokeAndFillCase, r);
                    TestCase d(inverted ? exampleInvStrokeAndFillCase
                                        : exampleStrokeAndFillCase, r);
                    a.compare(r, b, TestCase::kAllSame_ComparisonExpecation);
                    c.compare(r, d, TestCase::kAllSame_ComparisonExpecation);

                    const GrShape& strokeCase = shapes[index(inverted, dir, start, kStroke, dash)];
                    const GrShape& hairlineCase = shapes[index(inverted, dir, start, kHairline,
                                                               dash)];

                    TestCase e(strokeCase, r);
                    TestCase g(hairlineCase, r);

                    // Both hairline and stroke shapes must respect the dashing.
                    if (dash) {
                        // Dashing always ignores the inverseness. skbug.com/5421
                        TestCase f(exampleStrokeCase, r);
                        TestCase h(exampleHairlineCase, r);
                        unsigned expectedStart = canonicalize_rrect_start(start, rrect);
                        REPORTER_ASSERT(r, strokeCase.style().pathEffect());
                        REPORTER_ASSERT(r, hairlineCase.style().pathEffect());

                        REPORTER_ASSERT(r, strokeCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                              &queryInverted));
                        REPORTER_ASSERT(r, queryRR == rrect);
                        REPORTER_ASSERT(r, queryDir == dir);
                        REPORTER_ASSERT(r, queryStart == expectedStart);
                        REPORTER_ASSERT(r, !queryInverted);
                        REPORTER_ASSERT(r, hairlineCase.asRRect(&queryRR, &queryDir, &queryStart,
                                                                &queryInverted));
                        REPORTER_ASSERT(r, queryRR == rrect);
                        REPORTER_ASSERT(r, queryDir == dir);
                        REPORTER_ASSERT(r, queryStart == expectedStart);
                        REPORTER_ASSERT(r, !queryInverted);

                        // The pre-style case for the dash will match the non-dash example iff the
                        // dir and start match (dir=cw, start=0).
                        if (0 == expectedStart && SkPath::kCW_Direction == dir) {
                            e.compare(r, f, TestCase::kSameUpToPE_ComparisonExpecation);
                            g.compare(r, h, TestCase::kSameUpToPE_ComparisonExpecation);
                        } else {
                            e.compare(r, f, TestCase::kAllDifferent_ComparisonExpecation);
                            g.compare(r, h, TestCase::kAllDifferent_ComparisonExpecation);
                        }
                    } else {
                        TestCase f(inverted ? exampleInvStrokeCase : exampleStrokeCase, r);
                        TestCase h(inverted ? exampleInvHairlineCase : exampleHairlineCase, r);
                        REPORTER_ASSERT(r, !strokeCase.style().pathEffect());
                        REPORTER_ASSERT(r, !hairlineCase.style().pathEffect());
                        e.compare(r, f, TestCase::kAllSame_ComparisonExpecation);
                        g.compare(r, h, TestCase::kAllSame_ComparisonExpecation);
                    }
                }
            }
        }
    }
}

DEF_TEST(GrShape_lines, r) {
    static constexpr SkPoint kA { 1,  1};
    static constexpr SkPoint kB { 5, -9};
    static constexpr SkPoint kC {-3, 17};

    SkPath lineAB;
    lineAB.moveTo(kA);
    lineAB.lineTo(kB);

    SkPath lineBA;
    lineBA.moveTo(kB);
    lineBA.lineTo(kA);

    SkPath lineAC;
    lineAC.moveTo(kB);
    lineAC.lineTo(kC);

    SkPath invLineAB = lineAB;
    invLineAB.setFillType(SkPath::kInverseEvenOdd_FillType);

    SkPaint fill;
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(2.f);
    SkPaint hairline;
    hairline.setStyle(SkPaint::kStroke_Style);
    hairline.setStrokeWidth(0.f);
    SkPaint dash = stroke;
    dash.setPathEffect(make_dash());

    TestCase fillAB(r, lineAB, fill);
    TestCase fillEmpty(r, SkPath(), fill);
    fillAB.compare(r, fillEmpty, TestCase::kAllSame_ComparisonExpecation);
    REPORTER_ASSERT(r, !fillAB.baseShape().asLine(nullptr, nullptr));

    SkPath path;
    path.toggleInverseFillType();
    TestCase fillEmptyInverted(r, path, fill);
    TestCase fillABInverted(r, invLineAB, fill);
    fillABInverted.compare(r, fillEmptyInverted, TestCase::kAllSame_ComparisonExpecation);
    REPORTER_ASSERT(r, !fillABInverted.baseShape().asLine(nullptr, nullptr));

    TestCase strokeAB(r, lineAB, stroke);
    TestCase strokeBA(r, lineBA, stroke);
    TestCase strokeAC(r, lineAC, stroke);

    TestCase hairlineAB(r, lineAB, hairline);
    TestCase hairlineBA(r, lineBA, hairline);
    TestCase hairlineAC(r, lineAC, hairline);

    TestCase dashAB(r, lineAB, dash);
    TestCase dashBA(r, lineBA, dash);
    TestCase dashAC(r, lineAC, dash);

    strokeAB.compare(r, fillAB, TestCase::kAllDifferent_ComparisonExpecation);

    strokeAB.compare(r, strokeBA, TestCase::kAllSame_ComparisonExpecation);
    strokeAB.compare(r, strokeAC, TestCase::kAllDifferent_ComparisonExpecation);

    hairlineAB.compare(r, hairlineBA, TestCase::kAllSame_ComparisonExpecation);
    hairlineAB.compare(r, hairlineAC, TestCase::kAllDifferent_ComparisonExpecation);

    dashAB.compare(r, dashBA, TestCase::kAllDifferent_ComparisonExpecation);
    dashAB.compare(r, dashAC, TestCase::kAllDifferent_ComparisonExpecation);

    strokeAB.compare(r, hairlineAB, TestCase::kSameUpToStroke_ComparisonExpecation);

    // One of dashAB or dashBA should have the same line as strokeAB. It depends upon how
    // GrShape canonicalizes line endpoints (when it can, i.e. when not dashed).
    bool canonicalizeAsAB;
    SkPoint canonicalPts[2] {kA, kB};
    // Init these to suppress warnings.
    bool inverted = true;
    SkPoint pts[2] {{0, 0}, {0, 0}};
    REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted);
    if (pts[0] == kA && pts[1] == kB) {
        canonicalizeAsAB = true;
    } else if (pts[1] == kA && pts[0] == kB) {
        canonicalizeAsAB = false;
        SkTSwap(canonicalPts[0], canonicalPts[1]);
    } else {
        ERRORF(r, "Should return pts (a,b) or (b, a)");
        return;
    };

    strokeAB.compare(r, canonicalizeAsAB ? dashAB : dashBA,
                     TestCase::kSameUpToPE_ComparisonExpecation);
    REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted &&
                       pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
    REPORTER_ASSERT(r, hairlineAB.baseShape().asLine(pts, &inverted) && !inverted &&
                       pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
    REPORTER_ASSERT(r, dashAB.baseShape().asLine(pts, &inverted) && !inverted &&
                       pts[0] == kA && pts[1] == kB);
    REPORTER_ASSERT(r, dashBA.baseShape().asLine(pts, &inverted) && !inverted &&
                       pts[0] == kB && pts[1] == kA);


    TestCase strokeInvAB(r, invLineAB, stroke);
    TestCase hairlineInvAB(r, invLineAB, hairline);
    TestCase dashInvAB(r, invLineAB, dash);
    strokeInvAB.compare(r, strokeAB, TestCase::kAllDifferent_ComparisonExpecation);
    hairlineInvAB.compare(r, hairlineAB, TestCase::kAllDifferent_ComparisonExpecation);
    // Dashing ignores inverse.
    dashInvAB.compare(r, dashAB, TestCase::kAllSame_ComparisonExpecation);

    REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverted &&
                       pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
    REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inverted &&
                       pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
    // Dashing ignores inverse.
    REPORTER_ASSERT(r, dashInvAB.baseShape().asLine(pts, &inverted) && !inverted &&
                       pts[0] == kA && pts[1] == kB);

}

DEF_TEST(GrShape_stroked_lines, r) {
    // Paints to try
    SkPaint buttCap;
    buttCap.setStyle(SkPaint::kStroke_Style);
    buttCap.setStrokeWidth(4);
    buttCap.setStrokeCap(SkPaint::kButt_Cap);

    SkPaint squareCap = buttCap;
    squareCap.setStrokeCap(SkPaint::kSquare_Cap);

    SkPaint roundCap = buttCap;
    roundCap.setStrokeCap(SkPaint::kRound_Cap);

    // vertical
    SkPath linePath;
    linePath.moveTo(4, 4);
    linePath.lineTo(4, 5);

    SkPaint fill;

    make_TestCase(r, linePath, buttCap)->compare(
            r, TestCase(r, SkRect::MakeLTRB(2, 4, 6, 5), fill),
            TestCase::kAllSame_ComparisonExpecation);

    make_TestCase(r, linePath, squareCap)->compare(
            r, TestCase(r, SkRect::MakeLTRB(2, 2, 6, 7), fill),
            TestCase::kAllSame_ComparisonExpecation);

    make_TestCase(r, linePath, roundCap)->compare(r,
        TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fill),
        TestCase::kAllSame_ComparisonExpecation);

    // horizontal
    linePath.reset();
    linePath.moveTo(4, 4);
    linePath.lineTo(5, 4);

    make_TestCase(r, linePath, buttCap)->compare(
            r, TestCase(r, SkRect::MakeLTRB(4, 2, 5, 6), fill),
            TestCase::kAllSame_ComparisonExpecation);
    make_TestCase(r, linePath, squareCap)->compare(
            r, TestCase(r, SkRect::MakeLTRB(2, 2, 7, 6), fill),
            TestCase::kAllSame_ComparisonExpecation);
    make_TestCase(r, linePath, roundCap)->compare(
            r, TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fill),
            TestCase::kAllSame_ComparisonExpecation);

    // point
    linePath.reset();
    linePath.moveTo(4, 4);
    linePath.lineTo(4, 4);

    make_TestCase(r, linePath, buttCap)->compare(
            r, TestCase(r, SkRect::MakeEmpty(), fill),
            TestCase::kAllSame_ComparisonExpecation);
    make_TestCase(r, linePath, squareCap)->compare(
            r, TestCase(r, SkRect::MakeLTRB(2, 2, 6, 6), fill),
            TestCase::kAllSame_ComparisonExpecation);
    make_TestCase(r, linePath, roundCap)->compare(
            r, TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 6), 2, 2), fill),
            TestCase::kAllSame_ComparisonExpecation);
}

DEF_TEST(GrShape_short_path_keys, r) {
    SkPaint paints[4];
    paints[1].setStyle(SkPaint::kStroke_Style);
    paints[1].setStrokeWidth(5.f);
    paints[2].setStyle(SkPaint::kStroke_Style);
    paints[2].setStrokeWidth(0.f);
    paints[3].setStyle(SkPaint::kStrokeAndFill_Style);
    paints[3].setStrokeWidth(5.f);

    auto compare = [r, &paints] (const SkPath& pathA, const SkPath& pathB,
                                 TestCase::ComparisonExpecation expectation) {
        SkPath volatileA = pathA;
        SkPath volatileB = pathB;
        volatileA.setIsVolatile(true);
        volatileB.setIsVolatile(true);
        for (const SkPaint& paint : paints) {
            REPORTER_ASSERT(r, !GrShape(volatileA, paint).hasUnstyledKey());
            REPORTER_ASSERT(r, !GrShape(volatileB, paint).hasUnstyledKey());
            for (PathGeo::Invert invert : {PathGeo::Invert::kNo, PathGeo::Invert::kYes}) {
                TestCase caseA(PathGeo(pathA, invert), paint, r);
                TestCase caseB(PathGeo(pathB, invert), paint, r);
                caseA.compare(r, caseB, expectation);
            }
        }
    };

    SkPath pathA;
    SkPath pathB;

    // Two identical paths
    pathA.lineTo(10.f, 10.f);
    pathA.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);

    pathB.lineTo(10.f, 10.f);
    pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
    compare(pathA, pathB, TestCase::kAllSame_ComparisonExpecation);

    // Give path b a different point
    pathB.reset();
    pathB.lineTo(10.f, 10.f);
    pathB.conicTo(21.f, 20.f, 20.f, 30.f, 0.7f);
    compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);

    // Give path b a different conic weight
    pathB.reset();
    pathB.lineTo(10.f, 10.f);
    pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
    compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);

    // Give path b an extra lineTo verb
    pathB.reset();
    pathB.lineTo(10.f, 10.f);
    pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
    pathB.lineTo(50.f, 50.f);
    compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);

    // Give path b a close
    pathB.reset();
    pathB.lineTo(10.f, 10.f);
    pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
    pathB.close();
    compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
}

DEF_TEST(GrShape, reporter) {
    SkTArray<std::unique_ptr<Geo>> geos;
    SkTArray<std::unique_ptr<RRectPathGeo>> rrectPathGeos;

    for (auto r : { SkRect::MakeWH(10, 20),
                    SkRect::MakeWH(-10, -20),
                    SkRect::MakeWH(-10, 20),
                    SkRect::MakeWH(10, -20)}) {
        geos.emplace_back(new RectGeo(r));
        SkPath rectPath;
        rectPath.addRect(r);
        geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
                                           PathGeo::Invert::kNo));
        geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
                                           PathGeo::Invert::kYes));
        rrectPathGeos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
                                                    PathGeo::Invert::kNo));
    }
    for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)),
                     SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4),
                     SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) {
        geos.emplace_back(new RRectGeo(rr));
        test_rrect(reporter, rr);
        SkPath rectPath;
        rectPath.addRRect(rr);
        geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
                                           PathGeo::Invert::kNo));
        geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
                                           PathGeo::Invert::kYes));
        rrectPathGeos.emplace_back(new RRectPathGeo(rectPath, rr,
                                                    RRectPathGeo::RRectForStroke::kYes,
                                                    PathGeo::Invert::kNo));
    }

    {
        SkPath openRectPath;
        openRectPath.moveTo(0, 0);
        openRectPath.lineTo(10, 0);
        openRectPath.lineTo(10, 10);
        openRectPath.lineTo(0, 10);
        geos.emplace_back(new RRectPathGeo(
                    openRectPath, SkRect::MakeWH(10, 10),
                    RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kNo));
        geos.emplace_back(new RRectPathGeo(
                    openRectPath, SkRect::MakeWH(10, 10),
                    RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kYes));
        rrectPathGeos.emplace_back(new RRectPathGeo(
                    openRectPath, SkRect::MakeWH(10, 10),
                    RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kNo));
    }

    {
        SkPath quadPath;
        quadPath.quadTo(10, 10, 5, 8);
        geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kNo));
        geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kYes));
    }

    {
        SkPath linePath;
        linePath.lineTo(10, 10);
        geos.emplace_back(new PathGeo(linePath, PathGeo::Invert::kNo));
        geos.emplace_back(new PathGeo(linePath, PathGeo::Invert::kYes));
    }

    // Horizontal and vertical paths become rrects when stroked.
    {
        SkPath vLinePath;
        vLinePath.lineTo(0, 10);
        geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kNo));
        geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kYes));
    }

    {
        SkPath hLinePath;
        hLinePath.lineTo(10, 0);
        geos.emplace_back(new PathGeo(hLinePath, PathGeo::Invert::kNo));
        geos.emplace_back(new PathGeo(hLinePath, PathGeo::Invert::kYes));
    }

    for (int i = 0; i < geos.count(); ++i) {
        test_basic(reporter, *geos[i]);
        test_scale(reporter, *geos[i]);
        test_dash_fill(reporter, *geos[i]);
        test_null_dash(reporter, *geos[i]);
        // Test modifying various stroke params.
        test_stroke_param<SkScalar>(
                reporter, *geos[i],
                [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
                SkIntToScalar(2), SkIntToScalar(4));
        test_stroke_join(reporter, *geos[i]);
        test_stroke_cap(reporter, *geos[i]);
        test_miter_limit(reporter, *geos[i]);
        test_path_effect_makes_rrect(reporter, *geos[i]);
        test_unknown_path_effect(reporter, *geos[i]);
        test_path_effect_makes_empty_shape(reporter, *geos[i]);
        test_path_effect_fails(reporter, *geos[i]);
        test_make_hairline_path_effect(reporter, *geos[i]);
        test_volatile_path(reporter, *geos[i]);
    }

    for (int i = 0; i < rrectPathGeos.count(); ++i) {
        const RRectPathGeo& rrgeo = *rrectPathGeos[i];
        SkPaint fillPaint;
        TestCase fillPathCase(reporter, rrgeo.path(), fillPaint);
        SkRRect rrect;
        REPORTER_ASSERT(reporter, rrgeo.isNonPath(fillPaint) ==
                                  fillPathCase.baseShape().asRRect(&rrect, nullptr, nullptr,
                                                                   nullptr));
        if (rrgeo.isNonPath(fillPaint)) {
            TestCase fillPathCase2(reporter, rrgeo.path(), fillPaint);
            REPORTER_ASSERT(reporter, rrect == rrgeo.rrect());
            TestCase fillRRectCase(reporter, rrect, fillPaint);
            fillPathCase2.compare(reporter, fillRRectCase,
                                  TestCase::kAllSame_ComparisonExpecation);
        }
        SkPaint strokePaint;
        strokePaint.setStrokeWidth(3.f);
        strokePaint.setStyle(SkPaint::kStroke_Style);
        TestCase strokePathCase(reporter, rrgeo.path(), strokePaint);
        if (rrgeo.isNonPath(strokePaint)) {
            REPORTER_ASSERT(reporter, strokePathCase.baseShape().asRRect(&rrect, nullptr, nullptr,
                                                                         nullptr));
            REPORTER_ASSERT(reporter, rrect == rrgeo.rrect());
            TestCase strokeRRectCase(reporter, rrect, strokePaint);
            strokePathCase.compare(reporter, strokeRRectCase,
                                   TestCase::kAllSame_ComparisonExpecation);
        }
    }

    // Test a volatile empty path.
    test_volatile_path(reporter, PathGeo(SkPath(), PathGeo::Invert::kNo));
}

#endif
