/*
 * 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"

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, SkCanvas::kDifference_Op);
    surface->getCanvas()->concat(matrix);
    SkPaint whitePaint;
    whitePaint.setColor(SK_ColorWHITE);
    surface->getCanvas()->drawPath(path, whitePaint);
    SkPixmap pixmap;
    surface->getCanvas()->peekPixels(&pixmap);
#if defined(SK_BUILD_FOR_WIN)
    // The static constexpr version in #else causes cl.exe to crash.
    const uint8_t* kZeros = reinterpret_cast<uint8_t*>(calloc(kRes, 1));
#else
    static constexpr uint8_t kZeros[kRes] = {0};
#endif
    for (int y = 0; y < kRes; ++y) {
        const uint8_t* row = pixmap.addr8(0, y);
        if (0 != memcmp(kZeros, row, kRes)) {
            return false;
        }
    }
#ifdef SK_BUILD_FOR_WIN
    free(const_cast<uint8_t*>(kZeros));
#endif
    return true;
}

namespace {
/**
 * 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) && !fPath.isInverseFillType());
    }

    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);

        // 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());
            }
        }
    }

    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);
        }
    }
}

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());
}

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);
}

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.
    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);
    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);
    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);
    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);
    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.
     */
    class EmptyPathEffect : SkPathEffect {
    public:
        bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
                        const SkRect* cullR) const override {
            dst->reset();
            return true;
        }
        void computeFastBounds(SkRect* dst, const SkRect& src) const override {
            dst->setEmpty();
        }
        static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new EmptyPathEffect); }
        Factory getFactory() const override { return nullptr; }
        void toString(SkString*) const override {}
    private:
        EmptyPathEffect() {}
    };

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

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

    SkPaint peStroke;
    peStroke.setPathEffect(EmptyPathEffect::Make());
    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());
}

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));
}

void test_empty_shape(skiatest::Reporter* reporter) {
    SkPath emptyPath;
    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());

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

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

    // Dashing and stroking an empty path should have no effect
    SkPath emptyPath3;
    SkPaint dashAndStroke;
    dashAndStroke.setPathEffect(make_dash());
    dashAndStroke.setStrokeWidth(2.f);
    dashAndStroke.setStyle(SkPaint::kStroke_Style);
    TestCase dashAndStrokeEmptyCase(reporter, emptyPath3, dashAndStroke);
    dashAndStrokeEmptyCase.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);

    // Same for a rect.
    SkRect emptyRect = SkRect::MakeEmpty();
    TestCase dashAndStrokeEmptyRectCase(reporter, emptyRect, dashAndStroke);
    dashAndStrokeEmptyRectCase.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}) {
                        SkPathEffect* pe = dash ? dashEffect.get() : nullptr;
                        shapes[index(inverted, dir, start, style, dash)] =
                                GrShape(rrect, dir, start, SkToBool(inverted),
                                        GrStyle(strokeRecs[style], 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);
                    }
                }
            }
        }
    }
}

void test_lines(skiatest::Reporter* 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));

    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);

}

static void test_stroked_lines(skiatest::Reporter* 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;

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

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

    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);

    TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeLTRB(4, 2, 5, 6), fill),
                                           TestCase::kAllSame_ComparisonExpecation);
    TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 2, 7, 6), fill),
                                             TestCase::kAllSame_ComparisonExpecation);
    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);

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

static void test_short_path_keys(skiatest::Reporter* 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));

    test_empty_shape(reporter);

    test_lines(reporter);

    test_stroked_lines(reporter);

    test_short_path_keys(reporter);
}

#endif
