| Index: tests/GrShapeTest.cpp
|
| diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp
|
| index 9246c73f40f3419141bea2a97dbca5a1b3f8aba1..8ac27b4f98a5dbb32679d3afa1fc189c0ed47406 100644
|
| --- a/tests/GrShapeTest.cpp
|
| +++ b/tests/GrShapeTest.cpp
|
| @@ -74,14 +74,186 @@ static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds)
|
| }
|
|
|
| namespace {
|
| +/**
|
| + * Geo is a factory for creating a GrShape from another representation. It also answers some
|
| + * questions about expected behavior for GrShape given the inputs.
|
| + */
|
| +class Geo {
|
| +public:
|
| + virtual ~Geo() {};
|
| + virtual GrShape makeShape(const SkPaint&) const = 0;
|
| + virtual SkPath path() const = 0;
|
| + // These functions allow tests to check for special cases where style gets
|
| + // applied by GrShape in its constructor (without calling GrShape::applyStyle).
|
| + // These unfortunately rely on knowing details of GrShape's implementation.
|
| + // These predicates are factored out here to avoid littering the rest of the
|
| + // test code with GrShape implementation details.
|
| + virtual bool fillChangesGeom() const { return false; }
|
| + virtual bool strokeIsConvertedToFill() const { return false; }
|
| + virtual bool strokeAndFillIsConvertedToFill(const SkPaint&) const { return false; }
|
| + // Is this something we expect GrShape to recognize as something simpler than a path.
|
| + virtual bool isNonPath(const SkPaint& paint) const { return true; }
|
| +};
|
| +
|
| +class RectGeo : public Geo {
|
| +public:
|
| + RectGeo(const SkRect& rect) : fRect(rect) {}
|
| +
|
| + SkPath path() const override {
|
| + SkPath path;
|
| + path.addRect(fRect);
|
| + return path;
|
| + }
|
| +
|
| + GrShape makeShape(const SkPaint& paint) const override {
|
| + return GrShape(fRect, paint);
|
| + }
|
| +
|
| + bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
|
| + SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| + // Converted to an outset rectangle.
|
| + return paint.getStrokeJoin() == SkPaint::kMiter_Join &&
|
| + paint.getStrokeMiter() >= SK_ScalarSqrt2;
|
| + }
|
| +
|
| +private:
|
| + SkRect fRect;
|
| +};
|
| +
|
| +class RRectGeo : public Geo {
|
| +public:
|
| + RRectGeo(const SkRRect& rrect) : fRRect(rrect) {}
|
| +
|
| + GrShape makeShape(const SkPaint& paint) const override {
|
| + return GrShape(fRRect, paint);
|
| + }
|
| +
|
| + SkPath path() const override {
|
| + SkPath path;
|
| + path.addRRect(fRRect);
|
| + return path;
|
| + }
|
| +
|
| + bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
|
| + SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| + if (fRRect.isRect()) {
|
| + return RectGeo(fRRect.rect()).strokeAndFillIsConvertedToFill(paint);
|
| + }
|
| + return false;
|
| + }
|
| +
|
| +private:
|
| + SkRRect fRRect;
|
| +};
|
| +
|
| +class PathGeo : public Geo {
|
| +public:
|
| + enum class Invert { kNo, kYes };
|
| +
|
| + PathGeo(const SkPath& path, Invert invert) : fPath(path) {
|
| + SkASSERT(!path.isInverseFillType());
|
| + if (Invert::kYes == invert) {
|
| + if (fPath.getFillType() == SkPath::kEvenOdd_FillType) {
|
| + fPath.setFillType(SkPath::kInverseEvenOdd_FillType);
|
| + } else {
|
| + SkASSERT(fPath.getFillType() == SkPath::kWinding_FillType);
|
| + fPath.setFillType(SkPath::kInverseWinding_FillType);
|
| + }
|
| + }
|
| + }
|
| +
|
| + GrShape makeShape(const SkPaint& paint) const override {
|
| + return GrShape(fPath, paint);
|
| + }
|
| +
|
| + SkPath path() const override { return fPath; }
|
| +
|
| + bool fillChangesGeom() const override {
|
| + // unclosed rects get closed. Lines get turned into empty geometry
|
| + return this->isUnclosedRect() || (fPath.isLine(nullptr) && !fPath.isInverseFillType());
|
| + }
|
| +
|
| + bool strokeIsConvertedToFill() const override {
|
| + return this->isAxisAlignedLine();
|
| + }
|
| +
|
| + bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
|
| + SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| + if (this->isAxisAlignedLine()) {
|
| + // The fill is ignored (zero area) and the stroke is converted to a rrect.
|
| + return true;
|
| + }
|
| + SkRect rect;
|
| + unsigned start;
|
| + SkPath::Direction dir;
|
| + if (SkPathPriv::IsSimpleClosedRect(fPath, &rect, &dir, &start)) {
|
| + return RectGeo(rect).strokeAndFillIsConvertedToFill(paint);
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool isNonPath(const SkPaint& paint) const override {
|
| + return fPath.isLine(nullptr) || fPath.isEmpty();
|
| + }
|
| +
|
| +private:
|
| + bool isAxisAlignedLine() const {
|
| + SkPoint pts[2];
|
| + if (!fPath.isLine(pts)) {
|
| + return false;
|
| + }
|
| + return pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY;
|
| + }
|
| +
|
| + bool isUnclosedRect() const {
|
| + bool closed;
|
| + return fPath.isRect(nullptr, &closed, nullptr) && !closed;
|
| + }
|
| +
|
| + SkPath fPath;
|
| +};
|
| +
|
| +class RRectPathGeo : public PathGeo {
|
| +public:
|
| + enum class RRectForStroke { kNo, kYes };
|
| +
|
| + RRectPathGeo(const SkPath& path, const SkRRect& equivalentRRect, RRectForStroke rrectForStroke,
|
| + Invert invert)
|
| + : PathGeo(path, invert)
|
| + , fRRect(equivalentRRect)
|
| + , fRRectForStroke(rrectForStroke) {}
|
| +
|
| + RRectPathGeo(const SkPath& path, const SkRect& equivalentRect, RRectForStroke rrectForStroke,
|
| + Invert invert)
|
| + : RRectPathGeo(path, SkRRect::MakeRect(equivalentRect), rrectForStroke, invert) {}
|
| +
|
| + bool isNonPath(const SkPaint& paint) const override {
|
| + if (SkPaint::kFill_Style == paint.getStyle() || RRectForStroke::kYes == fRRectForStroke) {
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + const SkRRect& rrect() const { return fRRect; }
|
| +
|
| +private:
|
| + SkRRect fRRect;
|
| + RRectForStroke fRRectForStroke;
|
| +};
|
| +
|
| class TestCase {
|
| public:
|
| - template <typename GEO>
|
| - TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r,
|
| - SkScalar scale = SK_Scalar1) : fBase(geo, paint) {
|
| + TestCase(const Geo& geo, const SkPaint& paint, skiatest::Reporter* r,
|
| + SkScalar scale = SK_Scalar1) : fBase(geo.makeShape(paint)) {
|
| this->init(r, scale);
|
| }
|
|
|
| + template<typename... ShapeArgs>
|
| + TestCase(skiatest::Reporter* r, ShapeArgs... shapeArgs)
|
| + : fBase(shapeArgs...) {
|
| + this->init(r, SK_Scalar1);
|
| + }
|
| +
|
| TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Scalar1)
|
| : fBase(shape) {
|
| this->init(r, scale);
|
| @@ -433,78 +605,7 @@ static sk_sp<SkPathEffect> make_null_dash() {
|
| return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals), 0.f);
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////////////
|
| -// 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.
|
| -
|
| -static bool path_is_axis_aligned_line(const SkPath& path) {
|
| - SkPoint pts[2];
|
| - if (!path.isLine(pts)) {
|
| - return false;
|
| - }
|
| - return pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY;
|
| -}
|
| -
|
| -static bool path_is_unclosed_rect(const SkPath& path) {
|
| - bool closed;
|
| - return path.isRect(nullptr, &closed, nullptr) && !closed;
|
| -}
|
| -
|
| -// Will a GrShape constructed from a geometry perform a geometric transformation if the style is
|
| -// simple fill that would not otherwise be applied.
|
| -template <typename GEO> static bool fill_changes_geom(const GEO& geo) { return false; }
|
| -template <> bool fill_changes_geom<SkPath>(const SkPath& path) {
|
| - // unclosed rects get closed. Lines get turned into empty geometry
|
| - return path_is_unclosed_rect(path) || (path.isLine(nullptr) && !path.isInverseFillType());
|
| -}
|
| -
|
| -// Will a GrShape constructed from the geometry with a stroke style (without path effect) perform a
|
| -// geometric transformation that applies the the stroke immediately without storing a stroke style.
|
| -template <typename GEO> static bool stroke_is_converted_to_fill(const GEO& geo) { return false; }
|
| -template <> bool stroke_is_converted_to_fill(const SkPath& path) {
|
| - // converted to a rrect.
|
| - return path_is_axis_aligned_line(path);
|
| -}
|
| -
|
| -// Will a GrShape constructed from the geometry with a stroke-and-fill style (without path effect)
|
| -// perform a geometric transformation that applies the the stroke immediately without storing a
|
| -// stroke-and-fill style.
|
| -template <typename GEO> static bool stroke_and_fill_is_converted_to_fill(const GEO& geo, const SkPaint& paint);
|
| -template <> bool stroke_and_fill_is_converted_to_fill(const SkRect& rect, const SkPaint& paint) {
|
| - SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| - // Converted to an outset rectangle.
|
| - return paint.getStrokeJoin() == SkPaint::kMiter_Join &&
|
| - paint.getStrokeMiter() >= SK_ScalarSqrt2;
|
| -}
|
| -template <> bool stroke_and_fill_is_converted_to_fill(const SkPath& path, const SkPaint& paint) {
|
| - SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| - if (path_is_axis_aligned_line(path)) {
|
| - // 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(path, &rect, &dir, &start)) {
|
| - return stroke_and_fill_is_converted_to_fill<SkRect>(rect, paint);
|
| - }
|
| - return false;
|
| -}
|
| -template <> bool stroke_and_fill_is_converted_to_fill(const SkRRect& rr, const SkPaint& paint) {
|
| - SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style);
|
| - if (rr.isRect()) {
|
| - return stroke_and_fill_is_converted_to_fill<SkRect>(rr.rect(), paint);
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////////
|
| -
|
| -template<typename GEO>
|
| -static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| +static void test_basic(skiatest::Reporter* reporter, const Geo& geo) {
|
| sk_sp<SkPathEffect> dashPE = make_dash();
|
|
|
| TestCase::SelfExpectations expectations;
|
| @@ -527,7 +628,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter);
|
| expectations.fPEHasValidKey = true;
|
| expectations.fPEHasEffect = false;
|
| - expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo);
|
| + expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
|
| stroke2RoundBevelCase.testExpectations(reporter, expectations);
|
| TestCase(geo, stroke2RoundBevel, reporter).compare(reporter, stroke2RoundBevelCase,
|
| TestCase::kAllSame_ComparisonExpecation);
|
| @@ -542,7 +643,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase(geo, stroke2RoundBevelDash, reporter).compare(reporter, stroke2RoundBevelDashCase,
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| - if (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) {
|
| + if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) {
|
| fillCase.compare(reporter, stroke2RoundBevelCase,
|
| TestCase::kAllDifferent_ComparisonExpecation);
|
| fillCase.compare(reporter, stroke2RoundBevelDashCase,
|
| @@ -553,7 +654,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| fillCase.compare(reporter, stroke2RoundBevelDashCase,
|
| TestCase::kSameUpToPE_ComparisonExpecation);
|
| }
|
| - if (stroke_is_converted_to_fill(geo)) {
|
| + if (geo.strokeIsConvertedToFill()) {
|
| stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase,
|
| TestCase::kAllDifferent_ComparisonExpecation);
|
| } else {
|
| @@ -567,7 +668,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporter);
|
| expectations.fPEHasValidKey = true;
|
| expectations.fPEHasEffect = false;
|
| - expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo);
|
| + expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
|
| stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations);
|
| TestCase(geo, stroke2RoundBevelAndFill, reporter).compare(reporter,
|
| stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecation);
|
| @@ -577,7 +678,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash, reporter);
|
| expectations.fPEHasValidKey = true;
|
| expectations.fPEHasEffect = false;
|
| - expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo);
|
| + expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
|
| stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations);
|
| TestCase(geo, stroke2RoundBevelAndFillDash, reporter).compare(
|
| reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_ComparisonExpecation);
|
| @@ -590,7 +691,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| 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 (fill_changes_geom(geo)) {
|
| + if (geo.fillChangesGeom()) {
|
| hairlineCase.compare(reporter, fillCase, TestCase::kAllDifferent_ComparisonExpecation);
|
| } else {
|
| hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
|
| @@ -601,8 +702,7 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
|
|
| }
|
|
|
| -template<typename GEO>
|
| -static void test_scale(skiatest::Reporter* reporter, const GEO& geo) {
|
| +static void test_scale(skiatest::Reporter* reporter, const Geo& geo) {
|
| sk_sp<SkPathEffect> dashPE = make_dash();
|
|
|
| static const SkScalar kS1 = 1.f;
|
| @@ -628,7 +728,7 @@ static void test_scale(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase strokeCase1(geo, stroke, reporter, kS1);
|
| TestCase strokeCase2(geo, stroke, reporter, kS2);
|
| // Scale affects the stroke
|
| - if (stroke_is_converted_to_fill(geo)) {
|
| + if (geo.strokeIsConvertedToFill()) {
|
| REPORTER_ASSERT(reporter, !strokeCase1.baseShape().style().applies());
|
| strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_ComparisonExpecation);
|
| } else {
|
| @@ -656,7 +756,7 @@ static void test_scale(skiatest::Reporter* reporter, const GEO& geo) {
|
| // 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 (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillDash)) {
|
| + if (geo.strokeAndFillIsConvertedToFill(strokeAndFillDash)) {
|
| REPORTER_ASSERT(reporter, !strokeAndFillCase1.baseShape().style().applies());
|
| strokeAndFillCase1.compare(reporter, strokeAndFillCase2,
|
| TestCase::kAllSame_ComparisonExpecation);
|
| @@ -672,8 +772,8 @@ static void test_scale(skiatest::Reporter* reporter, const GEO& geo) {
|
| TestCase::kAllSame_ComparisonExpecation);
|
| }
|
|
|
| -template <typename GEO, typename T>
|
| -static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo,
|
| +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) {
|
| @@ -693,7 +793,7 @@ static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo,
|
| if (paramAffectsStroke) {
|
| // If stroking is immediately incorporated into a geometric transformation then the base
|
| // shapes will differ.
|
| - if (stroke_is_converted_to_fill(geo)) {
|
| + if (geo.strokeIsConvertedToFill()) {
|
| strokeACase.compare(reporter, strokeBCase,
|
| TestCase::kAllDifferent_ComparisonExpecation);
|
| } else {
|
| @@ -713,8 +813,8 @@ static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo,
|
| if (paramAffectsStroke) {
|
| // If stroking is immediately incorporated into a geometric transformation then the base
|
| // shapes will differ.
|
| - if (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillA) ||
|
| - stroke_and_fill_is_converted_to_fill(geo, strokeAndFillB)) {
|
| + if (geo.strokeAndFillIsConvertedToFill(strokeAndFillA) ||
|
| + geo.strokeAndFillIsConvertedToFill(strokeAndFillB)) {
|
| strokeAndFillACase.compare(reporter, strokeAndFillBCase,
|
| TestCase::kAllDifferent_ComparisonExpecation);
|
| } else {
|
| @@ -748,20 +848,22 @@ static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo,
|
| }
|
| }
|
|
|
| -template <typename GEO, typename T>
|
| -static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
| +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);
|
| };
|
|
|
| -template <typename GEO>
|
| -static void test_stroke_cap(skiatest::Reporter* reporter, const GEO& geo) {
|
| - GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle));
|
| +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<GEO, SkPaint::Cap>(
|
| + test_stroke_param_impl<SkPaint::Cap>(
|
| reporter,
|
| geo,
|
| [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
| @@ -774,15 +876,17 @@ static bool shape_known_not_to_have_joins(const GrShape& shape) {
|
| return shape.asLine(nullptr, nullptr) || shape.isEmpty();
|
| }
|
|
|
| -template <typename GEO>
|
| -static void test_stroke_join(skiatest::Reporter* reporter, const GEO& geo) {
|
| - GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle));
|
| +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<GEO, SkPaint::Join>(
|
| + test_stroke_param_impl<SkPaint::Join>(
|
| reporter,
|
| geo,
|
| [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
|
| @@ -790,8 +894,7 @@ static void test_stroke_join(skiatest::Reporter* reporter, const GEO& geo) {
|
| affectsStroke, true);
|
| };
|
|
|
| -template <typename GEO>
|
| -static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
| +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);
|
| @@ -802,12 +905,15 @@ static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
| p->setStrokeMiter(miter);
|
| };
|
|
|
| - GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle));
|
| + 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<GEO, SkScalar>(
|
| + test_stroke_param_impl<SkScalar>(
|
| reporter,
|
| geo,
|
| setMiterJoinAndLimit,
|
| @@ -817,7 +923,7 @@ static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
|
|
| // The miter limit should not affect stroked and dashed-stroked cases when the join type is
|
| // not miter.
|
| - test_stroke_param_impl<GEO, SkScalar>(
|
| + test_stroke_param_impl<SkScalar>(
|
| reporter,
|
| geo,
|
| setOtherJoinAndLimit,
|
| @@ -826,8 +932,7 @@ static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
| false);
|
| }
|
|
|
| -template<typename GEO>
|
| -static void test_dash_fill(skiatest::Reporter* reporter, const GEO& geo) {
|
| +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}) {
|
| @@ -840,8 +945,7 @@ static void test_dash_fill(skiatest::Reporter* reporter, const GEO& geo) {
|
| }
|
| }
|
|
|
| -template<typename GEO>
|
| -void test_null_dash(skiatest::Reporter* reporter, const GEO& geo) {
|
| +void test_null_dash(skiatest::Reporter* reporter, const Geo& geo) {
|
| SkPaint fill;
|
| SkPaint stroke;
|
| stroke.setStyle(SkPaint::kStroke_Style);
|
| @@ -864,21 +968,20 @@ void test_null_dash(skiatest::Reporter* reporter, const GEO& geo) {
|
| 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 (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) {
|
| + 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 (stroke_is_converted_to_fill(geo)) {
|
| + if (geo.strokeIsConvertedToFill()) {
|
| nullDashCase.compare(reporter, dashCase, TestCase::kAllDifferent_ComparisonExpecation);
|
| } else {
|
| nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExpecation);
|
| }
|
| }
|
|
|
| -template <typename GEO>
|
| -void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo) {
|
| +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.
|
| @@ -921,7 +1024,7 @@ void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo)
|
|
|
| // 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 (fill_changes_geom(geo)) {
|
| + if (geo.fillChangesGeom()) {
|
| fillGeoCase.compare(reporter, geoPECase, TestCase::kAllDifferent_ComparisonExpecation);
|
| fillGeoCase.compare(reporter, geoPEStrokeCase,
|
| TestCase::kAllDifferent_ComparisonExpecation);
|
| @@ -932,10 +1035,10 @@ void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo)
|
| geoPECase.compare(reporter, geoPEStrokeCase,
|
| TestCase::kSameUpToStroke_ComparisonExpecation);
|
|
|
| - TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter);
|
| + TestCase rrectFillCase(reporter, RRectPathEffect::RRect(), fill);
|
| SkPaint stroke = peStroke;
|
| stroke.setPathEffect(nullptr);
|
| - TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter);
|
| + TestCase rrectStrokeCase(reporter, RRectPathEffect::RRect(), stroke);
|
|
|
| SkRRect rrect;
|
| // Applying the path effect should make a SkRRect shape. There is no further stroking in the
|
| @@ -962,8 +1065,7 @@ void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo)
|
| rrectStrokeCase.appliedFullStyleKey());
|
| }
|
|
|
| -template <typename GEO>
|
| -void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) {
|
| +void test_unknown_path_effect(skiatest::Reporter* reporter, const Geo& geo) {
|
| /**
|
| * This path effect just adds two lineTos to the input path.
|
| */
|
| @@ -1003,8 +1105,7 @@ void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) {
|
| geoPEStrokeCase.testExpectations(reporter, expectations);
|
| }
|
|
|
| -template <typename GEO>
|
| -void test_make_hairline_path_effect(skiatest::Reporter* reporter, const GEO& geo, bool isNonPath) {
|
| +void test_make_hairline_path_effect(skiatest::Reporter* reporter, const Geo& geo) {
|
| /**
|
| * This path effect just changes the stroke rec to hairline.
|
| */
|
| @@ -1036,7 +1137,7 @@ void test_make_hairline_path_effect(skiatest::Reporter* reporter, const GEO& geo
|
| peCase.baseShape().asPath(&a);
|
| peCase.appliedPathEffectShape().asPath(&b);
|
| peCase.appliedFullStyleShape().asPath(&c);
|
| - if (isNonPath) {
|
| + 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.
|
| @@ -1058,26 +1159,21 @@ void test_make_hairline_path_effect(skiatest::Reporter* reporter, const GEO& geo
|
| REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHairline());
|
| }
|
|
|
| -/**
|
| - * isNonPath indicates whether the initial shape made from the path is expected to be recognized
|
| - * as a simpler shape type (e.g. rrect)
|
| - */
|
| -void test_volatile_path(skiatest::Reporter* reporter, const SkPath& path,
|
| - bool isNonPath) {
|
| - SkPath vPath(path);
|
| +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(vPath, dashAndStroke, reporter);
|
| + 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 (isNonPath) {
|
| + 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(path, dashAndStroke, reporter);
|
| + TestCase nonVolatileCase(reporter, geo.path(), dashAndStroke);
|
| volatileCase.compare(reporter, nonVolatileCase, TestCase::kAllSame_ComparisonExpecation);
|
| } else {
|
| // None of the keys should be valid.
|
| @@ -1088,8 +1184,7 @@ void test_volatile_path(skiatest::Reporter* reporter, const SkPath& path,
|
| }
|
| }
|
|
|
| -template <typename GEO>
|
| -void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const GEO& geo) {
|
| +void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const Geo& geo) {
|
| /**
|
| * This path effect returns an empty path.
|
| */
|
| @@ -1137,8 +1232,7 @@ void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const GEO&
|
| REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty());
|
| }
|
|
|
| -template <typename GEO>
|
| -void test_path_effect_fails(skiatest::Reporter* reporter, const GEO& geo) {
|
| +void test_path_effect_fails(skiatest::Reporter* reporter, const Geo& geo) {
|
| /**
|
| * This path effect always fails to apply.
|
| */
|
| @@ -1203,7 +1297,7 @@ void test_path_effect_fails(skiatest::Reporter* reporter, const GEO& geo) {
|
| void test_empty_shape(skiatest::Reporter* reporter) {
|
| SkPath emptyPath;
|
| SkPaint fill;
|
| - TestCase fillEmptyCase(emptyPath, fill, reporter);
|
| + TestCase fillEmptyCase(reporter, emptyPath, fill);
|
| REPORTER_ASSERT(reporter, fillEmptyCase.baseShape().isEmpty());
|
| REPORTER_ASSERT(reporter, fillEmptyCase.appliedPathEffectShape().isEmpty());
|
| REPORTER_ASSERT(reporter, fillEmptyCase.appliedFullStyleShape().isEmpty());
|
| @@ -1221,7 +1315,7 @@ void test_empty_shape(skiatest::Reporter* reporter) {
|
| SkPaint stroke;
|
| stroke.setStrokeWidth(2.f);
|
| stroke.setStyle(SkPaint::kStroke_Style);
|
| - TestCase strokeEmptyCase(emptyPath2, stroke, reporter);
|
| + TestCase strokeEmptyCase(reporter, emptyPath2, stroke);
|
| strokeEmptyCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // Dashing and stroking an empty path should have no effect
|
| @@ -1230,20 +1324,20 @@ void test_empty_shape(skiatest::Reporter* reporter) {
|
| dashAndStroke.setPathEffect(make_dash());
|
| dashAndStroke.setStrokeWidth(2.f);
|
| dashAndStroke.setStyle(SkPaint::kStroke_Style);
|
| - TestCase dashAndStrokeEmptyCase(emptyPath3, dashAndStroke, reporter);
|
| + TestCase dashAndStrokeEmptyCase(reporter, emptyPath3, dashAndStroke);
|
| dashAndStrokeEmptyCase.compare(reporter, fillEmptyCase,
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // A shape made from an empty rrect should behave the same as an empty path.
|
| SkRRect emptyRRect = SkRRect::MakeRect(SkRect::MakeEmpty());
|
| REPORTER_ASSERT(reporter, emptyRRect.getType() == SkRRect::kEmpty_Type);
|
| - TestCase dashAndStrokeEmptyRRectCase(emptyRRect, dashAndStroke, reporter);
|
| + TestCase dashAndStrokeEmptyRRectCase(reporter, emptyRRect, dashAndStroke);
|
| dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase,
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // Same for a rect.
|
| SkRect emptyRect = SkRect::MakeEmpty();
|
| - TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter);
|
| + TestCase dashAndStrokeEmptyRectCase(reporter, emptyRect, dashAndStroke);
|
| dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase,
|
| TestCase::kAllSame_ComparisonExpecation);
|
| }
|
| @@ -1535,22 +1629,22 @@ void test_lines(skiatest::Reporter* r) {
|
| SkPaint dash = stroke;
|
| dash.setPathEffect(make_dash());
|
|
|
| - TestCase fillAB(lineAB, fill, r);
|
| - TestCase fillEmpty(SkPath(), fill, r);
|
| + TestCase fillAB(r, lineAB, fill);
|
| + TestCase fillEmpty(r, SkPath(), fill);
|
| fillAB.compare(r, fillEmpty, TestCase::kAllSame_ComparisonExpecation);
|
| REPORTER_ASSERT(r, !fillAB.baseShape().asLine(nullptr, nullptr));
|
|
|
| - TestCase strokeAB(lineAB, stroke, r);
|
| - TestCase strokeBA(lineBA, stroke, r);
|
| - TestCase strokeAC(lineAC, stroke, r);
|
| + TestCase strokeAB(r, lineAB, stroke);
|
| + TestCase strokeBA(r, lineBA, stroke);
|
| + TestCase strokeAC(r, lineAC, stroke);
|
|
|
| - TestCase hairlineAB(lineAB, hairline, r);
|
| - TestCase hairlineBA(lineBA, hairline, r);
|
| - TestCase hairlineAC(lineAC, hairline, r);
|
| + TestCase hairlineAB(r, lineAB, hairline);
|
| + TestCase hairlineBA(r, lineBA, hairline);
|
| + TestCase hairlineAC(r, lineAC, hairline);
|
|
|
| - TestCase dashAB(lineAB, dash, r);
|
| - TestCase dashBA(lineBA, dash, r);
|
| - TestCase dashAC(lineAC, dash, r);
|
| + TestCase dashAB(r, lineAB, dash);
|
| + TestCase dashBA(r, lineBA, dash);
|
| + TestCase dashAC(r, lineAC, dash);
|
|
|
| strokeAB.compare(r, fillAB, TestCase::kAllDifferent_ComparisonExpecation);
|
|
|
| @@ -1595,9 +1689,9 @@ void test_lines(skiatest::Reporter* r) {
|
| pts[0] == kB && pts[1] == kA);
|
|
|
|
|
| - TestCase strokeInvAB(invLineAB, stroke, r);
|
| - TestCase hairlineInvAB(invLineAB, hairline, r);
|
| - TestCase dashInvAB(invLineAB, dash, r);
|
| + 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.
|
| @@ -1633,14 +1727,14 @@ static void test_stroked_lines(skiatest::Reporter* r) {
|
|
|
| SkPaint fill;
|
|
|
| - TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 4, 6, 5), fill, r),
|
| + TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 4, 6, 5), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| - TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2, 6, 7), fill, r),
|
| + TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 2, 6, 7), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| - TestCase(linePath, roundCap, r).compare(r,
|
| - TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fill, r),
|
| + TestCase(r, linePath, roundCap).compare(r,
|
| + TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // horizontal
|
| @@ -1648,12 +1742,12 @@ static void test_stroked_lines(skiatest::Reporter* r) {
|
| linePath.moveTo(4, 4);
|
| linePath.lineTo(5, 4);
|
|
|
| - TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(4, 2, 5, 6), fill, r),
|
| + TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeLTRB(4, 2, 5, 6), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
| - TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2, 7, 6), fill, r),
|
| + TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 2, 7, 6), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
| - TestCase(linePath, roundCap, r).compare(r,
|
| - TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fill, r),
|
| + TestCase(r, linePath, roundCap).compare(r,
|
| + TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // point
|
| @@ -1661,183 +1755,135 @@ static void test_stroked_lines(skiatest::Reporter* r) {
|
| linePath.moveTo(4, 4);
|
| linePath.lineTo(4, 4);
|
|
|
| - TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeEmpty(), fill, r),
|
| + TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeEmpty(), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
| - TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2, 6, 6), fill, r),
|
| + TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 2, 6, 6), fill),
|
| TestCase::kAllSame_ComparisonExpecation);
|
| - TestCase(linePath, roundCap, r).compare(r,
|
| - TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 6), 2, 2), fill, r),
|
| + 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, 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)}) {
|
| - test_basic(reporter, r);
|
| - test_scale(reporter, r);
|
| - test_dash_fill(reporter, r);
|
| - test_null_dash(reporter, r);
|
| - // Test modifying various stroke params.
|
| - test_stroke_param<SkRect, SkScalar>(
|
| - reporter, r,
|
| - [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
| - SkIntToScalar(2), SkIntToScalar(4));
|
| - test_stroke_join(reporter, r);
|
| - test_stroke_cap(reporter, r);
|
| - test_miter_limit(reporter, r);
|
| - test_path_effect_makes_rrect(reporter, r);
|
| - test_unknown_path_effect(reporter, r);
|
| - test_path_effect_makes_empty_shape(reporter, r);
|
| - test_path_effect_fails(reporter, r);
|
| - test_make_hairline_path_effect(reporter, r, true);
|
| - GrShape shape(r);
|
| - REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr));
|
| + 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))}) {
|
| - test_basic(reporter, rr);
|
| + geos.emplace_back(new RRectGeo(rr));
|
| test_rrect(reporter, rr);
|
| - test_scale(reporter, rr);
|
| - test_dash_fill(reporter, rr);
|
| - test_null_dash(reporter, rr);
|
| - // Test modifying various stroke params.
|
| - test_stroke_param<SkRRect, SkScalar>(
|
| - reporter, rr,
|
| - [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
| - SkIntToScalar(2), SkIntToScalar(4));
|
| - test_stroke_join(reporter, rr);
|
| - test_stroke_cap(reporter, rr);
|
| - test_miter_limit(reporter, rr);
|
| - test_path_effect_makes_rrect(reporter, rr);
|
| - test_unknown_path_effect(reporter, rr);
|
| - test_path_effect_makes_empty_shape(reporter, rr);
|
| - test_path_effect_fails(reporter, rr);
|
| - test_make_hairline_path_effect(reporter, rr, true);
|
| - GrShape shape(rr);
|
| - REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr));
|
| + 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));
|
| }
|
|
|
| - struct TestPath {
|
| - TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke, bool isLine,
|
| - const SkRRect& rrect)
|
| - : fPath(path)
|
| - , fIsRRectForFill(isRRectFill)
|
| - , fIsRRectForStroke(isRRectStroke)
|
| - , fIsLine(isLine)
|
| - , fRRect(rrect) {}
|
| - SkPath fPath;
|
| - bool fIsRRectForFill;
|
| - bool fIsRRectForStroke;
|
| - bool fIsLine;
|
| - SkRRect fRRect;
|
| - };
|
| - SkTArray<TestPath> paths;
|
| -
|
| - SkPath circlePath;
|
| - circlePath.addCircle(10, 10, 10);
|
| - paths.emplace_back(circlePath, true, true, false, SkRRect::MakeOval(SkRect::MakeWH(20,20)));
|
| -
|
| - SkPath rectPath;
|
| - rectPath.addRect(SkRect::MakeWH(10, 10));
|
| - paths.emplace_back(rectPath, true, true, false, SkRRect::MakeRect(SkRect::MakeWH(10, 10)));
|
| -
|
| SkPath openRectPath;
|
| openRectPath.moveTo(0, 0);
|
| openRectPath.lineTo(10, 0);
|
| openRectPath.lineTo(10, 10);
|
| openRectPath.lineTo(0, 10);
|
| - paths.emplace_back(openRectPath, true, false, false, SkRRect::MakeRect(SkRect::MakeWH(10, 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);
|
| - paths.emplace_back(quadPath, false, false, false, SkRRect());
|
| + geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kNo));
|
| + geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kYes));
|
|
|
| SkPath linePath;
|
| linePath.lineTo(10, 10);
|
| - paths.emplace_back(linePath, false, false, true, SkRRect());
|
| + 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);
|
| - paths.emplace_back(vLinePath, false, false, true, SkRRect());
|
| + geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kNo));
|
| + geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kYes));
|
|
|
| SkPath hLinePath;
|
| hLinePath.lineTo(10, 0);
|
| - paths.emplace_back(hLinePath, false, false, true, SkRRect());
|
| -
|
| - for (auto testPath : paths) {
|
| - for (bool inverseFill : {false, true}) {
|
| - if (inverseFill) {
|
| - if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) {
|
| - testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType);
|
| - } else {
|
| - SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_FillType);
|
| - testPath.fPath.setFillType(SkPath::kInverseWinding_FillType);
|
| - }
|
| - }
|
| - const SkPath& path = testPath.fPath;
|
| - test_basic(reporter, path);
|
| - test_null_dash(reporter, path);
|
| - test_path_effect_makes_rrect(reporter, path);
|
| - test_scale(reporter, path);
|
| - // This test uses a stroking paint, hence use of fIsRRectForStroke
|
| - test_volatile_path(reporter, path, testPath.fIsRRectForStroke || testPath.fIsLine);
|
| - test_dash_fill(reporter, path);
|
| - // Test modifying various stroke params.
|
| - test_stroke_param<SkPath, SkScalar>(
|
| - reporter, path,
|
| + 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, path);
|
| - test_stroke_cap(reporter, path);
|
| - test_miter_limit(reporter, path);
|
| - test_unknown_path_effect(reporter, path);
|
| - test_path_effect_makes_empty_shape(reporter, path);
|
| - test_path_effect_fails(reporter, path);
|
| - test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForStroke ||
|
| - testPath.fIsLine);
|
| - }
|
| + 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 (auto testPath : paths) {
|
| - const SkPath& path = testPath.fPath;
|
| -
|
| + for (int i = 0; i < rrectPathGeos.count(); ++i) {
|
| + const RRectPathGeo& rrgeo = *rrectPathGeos[i];
|
| SkPaint fillPaint;
|
| - TestCase fillPathCase(path, fillPaint, reporter);
|
| + TestCase fillPathCase(reporter, rrgeo.path(), fillPaint);
|
| SkRRect rrect;
|
| - REPORTER_ASSERT(reporter, testPath.fIsRRectForFill ==
|
| + REPORTER_ASSERT(reporter, rrgeo.isNonPath(fillPaint) ==
|
| fillPathCase.baseShape().asRRect(&rrect, nullptr, nullptr,
|
| nullptr));
|
| - if (testPath.fIsRRectForFill) {
|
| - TestCase fillPathCase2(testPath.fPath, fillPaint, reporter);
|
| - REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
|
| - TestCase fillRRectCase(rrect, fillPaint, reporter);
|
| + 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(path, strokePaint, reporter);
|
| - if (testPath.fIsRRectForStroke) {
|
| + TestCase strokePathCase(reporter, rrgeo.path(), strokePaint);
|
| + if (rrgeo.isNonPath(strokePaint)) {
|
| REPORTER_ASSERT(reporter, strokePathCase.baseShape().asRRect(&rrect, nullptr, nullptr,
|
| nullptr));
|
| - }
|
| -
|
| - if (testPath.fIsRRectForStroke) {
|
| - REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
|
| - TestCase strokeRRectCase(rrect, strokePaint, reporter);
|
| + 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, SkPath(), true);
|
| + test_volatile_path(reporter, PathGeo(SkPath(), PathGeo::Invert::kNo));
|
|
|
| test_empty_shape(reporter);
|
|
|
|
|