/*
 * 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"
#include "GrShape.h"
#include "SkCanvas.h"
#include "SkDashPathEffect.h"
#include "SkPath.h"
#include "SkPathOps.h"
#include "SkRectPriv.h"
#include "SkSurface.h"
#include "SkClipOpPriv.h"

#include <utility>

uint32_t GrShape::testingOnly_getOriginalGenerationID() const {
    if (const auto* lp = this->originalPathForListeners()) {
        return lp->getGenerationID();
    }
    return SkPath().getGenerationID();
}

bool GrShape::testingOnly_isPath() const {
    return Type::kPath == fType;
}

bool GrShape::testingOnly_isNonVolatilePath() const {
    return Type::kPath == fType && !fPathData.fPath.isVolatile();
}

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 = 2;
    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 baseIsNonVolatilePath = base.testingOnly_isNonVolatilePath();
    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 or a volatile path, our original path should have
    // been reset.
    REPORTER_ASSERT(r, baseIsNonVolatilePath == (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 (baseIsNonVolatilePath) {
        REPORTER_ASSERT(r, baseID == peID);
    }

    if (peStrokeIsPath) {
        REPORTER_ASSERT(r, peID == peStrokeID);
        REPORTER_ASSERT(r, peStrokeID == fullID);
    }

    if (baseIsNonVolatilePath && 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 ArcGeo : public Geo {
public:
    ArcGeo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter)
            : fOval(oval)
            , fStartAngle(startAngle)
            , fSweepAngle(sweepAngle)
            , fUseCenter(useCenter) {}

    SkPath path() const override {
        SkPath path;
        SkPathPriv::CreateDrawArcPath(&path, fOval, fStartAngle, fSweepAngle, fUseCenter, false);
        return path;
    }

    GrShape makeShape(const SkPaint& paint) const override {
        return GrShape::MakeArc(fOval, fStartAngle, fSweepAngle, fUseCenter, GrStyle(paint));
    }

    // GrShape specializes when created from arc params but it doesn't recognize arcs from SkPath.
    bool isNonPath(const SkPaint& paint) const override { return false; }

private:
    SkRect fOval;
    SkScalar fStartAngle;
    SkScalar fSweepAngle;
    bool fUseCenter;
};

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(new GrShape(geo.makeShape(paint))) {
        this->init(r, scale);
    }

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

    TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Scalar1)
            : fBase(new GrShape(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.reset(new GrShape);
        fAppliedPEThenStroke.reset(new GrShape);
        fAppliedFull.reset(new GrShape);

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

    std::unique_ptr<GrShape> fBase;
    std::unique_ptr<GrShape> fAppliedPE;
    std::unique_ptr<GrShape> fAppliedPEThenStroke;
    std::unique_ptr<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; }
    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;
            SkRectPriv::GrowToInclude(dst, {0, 0});
            SkRectPriv::GrowToInclude(dst, {100, 100});
        }
        static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new AddLineTosPathEffect); }
        Factory getFactory() const override { return nullptr; }
    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; }
    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; }
    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; }
    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);
    stroke.setStrokeJoin(SkPaint::kRound_Join);
    stroke.setStrokeCap(SkPaint::kRound_Cap);
    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 when filled but not
    // when stroked. However, dashing an empty rrect produces an empty path leaving nothing to
    // stroke - so equivalent to filling an empty path.
    SkRRect emptyRRect = SkRRect::MakeEmpty();
    REPORTER_ASSERT(reporter, emptyRRect.getType() == SkRRect::kEmpty_Type);

    TestCase fillEmptyRRectCase(reporter, emptyRRect, fill);
    fillEmptyRRectCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);

    TestCase strokeEmptyRRectCase(reporter, emptyRRect, stroke);
    strokeEmptyRRectCase.compare(reporter, strokeEmptyCase,
                                 TestCase::kAllDifferent_ComparisonExpecation);

    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 fillInvertedEmptyRRectCase(reporter, emptyRRect, kDir, kStart, true, GrStyle(fill));
    fillInvertedEmptyRRectCase.compare(reporter, fillInvertedEmptyCase,
                                       TestCase::kAllSame_ComparisonExpecation);

    TestCase strokeInvertedEmptyRRectCase(reporter, emptyRRect, kDir, kStart, true,
                                          GrStyle(stroke));
    strokeInvertedEmptyRRectCase.compare(reporter, strokeInvertedEmptyCase,
                                         TestCase::kAllDifferent_ComparisonExpecation);

    TestCase dashAndStrokeEmptyInvertedRRectCase(reporter, emptyRRect, kDir, kStart, true,
                                                 GrStyle(dashAndStroke));
    dashAndStrokeEmptyInvertedRRectCase.compare(reporter, fillEmptyCase,
                                                TestCase::kAllSame_ComparisonExpecation);

    // Same for a rect.
    SkRect emptyRect = SkRect::MakeEmpty();
    TestCase fillEmptyRectCase(reporter, emptyRect, fill);
    fillEmptyRectCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);

    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;
        using std::swap;
        swap(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) {
    static constexpr SkScalar kIntervals1[] = {1.f, 0.f};
    auto dash1 = SkDashPathEffect::Make(kIntervals1, SK_ARRAY_COUNT(kIntervals1), 0.f);
    REPORTER_ASSERT(r, dash1);
    static constexpr SkScalar kIntervals2[] = {10.f, 0.f, 5.f, 0.f};
    auto dash2 = SkDashPathEffect::Make(kIntervals2, SK_ARRAY_COUNT(kIntervals2), 10.f);
    REPORTER_ASSERT(r, dash2);

    sk_sp<SkPathEffect> pathEffects[] = {nullptr, std::move(dash1), std::move(dash2)};

    for (const auto& pe : pathEffects) {
        // Paints to try
        SkPaint buttCap;
        buttCap.setStyle(SkPaint::kStroke_Style);
        buttCap.setStrokeWidth(4);
        buttCap.setStrokeCap(SkPaint::kButt_Cap);
        buttCap.setPathEffect(pe);

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

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

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

    // Arcs
    geos.emplace_back(new ArcGeo(SkRect::MakeWH(200, 100), 12.f, 110.f, false));
    geos.emplace_back(new ArcGeo(SkRect::MakeWH(200, 100), 12.f, 110.f, true));

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

DEF_TEST(GrShape_arcs, reporter) {
    SkStrokeRec roundStroke(SkStrokeRec::kFill_InitStyle);
    roundStroke.setStrokeStyle(2.f);
    roundStroke.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 1.f);

    SkStrokeRec squareStroke(roundStroke);
    squareStroke.setStrokeParams(SkPaint::kSquare_Cap, SkPaint::kRound_Join, 1.f);

    SkStrokeRec roundStrokeAndFill(roundStroke);
    roundStrokeAndFill.setStrokeStyle(2.f, true);

    static constexpr SkScalar kIntervals[] = {1, 2};
    auto dash = SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 1.5f);

    SkTArray<GrStyle> styles;
    styles.push_back(GrStyle::SimpleFill());
    styles.push_back(GrStyle::SimpleHairline());
    styles.push_back(GrStyle(roundStroke, nullptr));
    styles.push_back(GrStyle(squareStroke, nullptr));
    styles.push_back(GrStyle(roundStrokeAndFill, nullptr));
    styles.push_back(GrStyle(roundStroke, dash));

    for (const auto& style : styles) {
        // An empty rect never draws anything according to SkCanvas::drawArc() docs.
        TestCase emptyArc(GrShape::MakeArc(SkRect::MakeEmpty(), 0, 90.f, false, style), reporter);
        TestCase emptyPath(reporter, SkPath(), style);
        emptyArc.compare(reporter, emptyPath, TestCase::kAllSame_ComparisonExpecation);

        static constexpr SkRect kOval1{0, 0, 50, 50};
        static constexpr SkRect kOval2{50, 0, 100, 50};
        // Test that swapping starting and ending angle doesn't change the shape unless the arc
        // has a path effect. Also test that different ovals produce different shapes.
        TestCase arc1CW(GrShape::MakeArc(kOval1, 0, 90.f, false, style), reporter);
        TestCase arc1CCW(GrShape::MakeArc(kOval1, 90.f, -90.f, false, style), reporter);

        TestCase arc1CWWithCenter(GrShape::MakeArc(kOval1, 0, 90.f, true, style), reporter);
        TestCase arc1CCWWithCenter(GrShape::MakeArc(kOval1, 90.f, -90.f, true, style), reporter);

        TestCase arc2CW(GrShape::MakeArc(kOval2, 0, 90.f, false, style), reporter);
        TestCase arc2CWWithCenter(GrShape::MakeArc(kOval2, 0, 90.f, true, style), reporter);

        auto reversedExepectations = style.hasPathEffect()
                                             ? TestCase::kAllDifferent_ComparisonExpecation
                                             : TestCase::kAllSame_ComparisonExpecation;
        arc1CW.compare(reporter, arc1CCW, reversedExepectations);
        arc1CWWithCenter.compare(reporter, arc1CCWWithCenter, reversedExepectations);
        arc1CW.compare(reporter, arc2CW, TestCase::kAllDifferent_ComparisonExpecation);
        arc1CW.compare(reporter, arc1CWWithCenter, TestCase::kAllDifferent_ComparisonExpecation);
        arc1CWWithCenter.compare(reporter, arc2CWWithCenter,
                                 TestCase::kAllDifferent_ComparisonExpecation);

        // Test that two arcs that start at the same angle but specified differently are equivalent.
        TestCase arc3A(GrShape::MakeArc(kOval1, 224.f, 73.f, false, style), reporter);
        TestCase arc3B(GrShape::MakeArc(kOval1, 224.f - 360.f, 73.f, false, style), reporter);
        arc3A.compare(reporter, arc3B, TestCase::kAllDifferent_ComparisonExpecation);

        // Test that an arc that traverses the entire oval (and then some) is equivalent to the
        // oval itself unless there is a path effect.
        TestCase ovalArc(GrShape::MakeArc(kOval1, 150.f, -790.f, false, style), reporter);
        TestCase oval(GrShape(SkRRect::MakeOval(kOval1)), reporter);
        auto ovalExpectations = style.hasPathEffect() ? TestCase::kAllDifferent_ComparisonExpecation
                                                      : TestCase::kAllSame_ComparisonExpecation;
        if (style.strokeRec().getWidth() >= 0 && style.strokeRec().getCap() != SkPaint::kButt_Cap) {
            ovalExpectations = TestCase::kAllDifferent_ComparisonExpecation;
        }
        ovalArc.compare(reporter, oval, ovalExpectations);

        // If the the arc starts/ends at the center then it is then equivalent to the oval only for
        // simple fills.
        TestCase ovalArcWithCenter(GrShape::MakeArc(kOval1, 304.f, 1225.f, true, style), reporter);
        ovalExpectations = style.isSimpleFill() ? TestCase::kAllSame_ComparisonExpecation
                                                : TestCase::kAllDifferent_ComparisonExpecation;
        ovalArcWithCenter.compare(reporter, oval, ovalExpectations);
    }
}
