From af88ec37124846a0168a4ab061bf10cc6030c2d6 Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Tue, 24 Apr 2018 12:18:37 +0000 Subject: [PATCH] Revert "Add arcs as a specialized geometry to GrShape." This reverts commit 255bcf57ffd9db368cd66ca9697549efd799153e. Reason for revert: layout and scuba image diffs Original change's description: > Add arcs as a specialized geometry to GrShape. > > BUG: skia:7794 > > Change-Id: I484693711f48e55631732a0f4ee97e2848dec89d > Reviewed-on: https://skia-review.googlesource.com/122900 > Commit-Queue: Brian Salomon > Reviewed-by: Robert Phillips TBR=bsalomon@google.com,robertphillips@google.com Change-Id: I9293b8fbb535d940bca5fc30a95908416b9eb7a7 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/123362 Reviewed-by: Mike Klein Commit-Queue: Mike Klein --- src/core/SkPath.cpp | 39 +---------- src/core/SkPathPriv.h | 6 -- src/core/SkStrokeRec.cpp | 16 ++--- src/gpu/GrRenderTargetContext.cpp | 7 +- src/gpu/GrShape.cpp | 82 +--------------------- src/gpu/GrShape.h | 58 +++------------- tests/GrShapeTest.cpp | 110 +----------------------------- 7 files changed, 25 insertions(+), 293 deletions(-) diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 6ffac08664..54d7a69177 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -1304,19 +1304,6 @@ void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, SkPoint singlePt; - // Adds a move-to to 'pt' if forceMoveTo is true. Otherwise a lineTo unless we're sufficiently - // close to 'pt' currently. This prevents spurious lineTos when adding a series of contiguous - // arcs from the same oval. - auto addPt = [&forceMoveTo, this](const SkPoint& pt) { - SkPoint lastPt; - if (forceMoveTo) { - this->moveTo(pt); - } else if (!this->getLastPt(&lastPt) || !SkScalarNearlyEqual(lastPt.fX, pt.fX) || - !SkScalarNearlyEqual(lastPt.fY, pt.fY)) { - this->lineTo(pt); - } - }; - // At this point, we know that the arc is not a lone point, but startV == stopV // indicates that the sweepAngle is too small such that angles_to_unit_vectors // cannot handle it. @@ -1331,7 +1318,7 @@ void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, // make sin(endAngle) to be 0 which will then draw a dot. singlePt.set(oval.centerX() + radiusX * sk_float_cos(endAngle), oval.centerY() + radiusY * sk_float_sin(endAngle)); - addPt(singlePt); + forceMoveTo ? this->moveTo(singlePt) : this->lineTo(singlePt); return; } @@ -1340,12 +1327,12 @@ void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, if (count) { this->incReserve(count * 2 + 1); const SkPoint& pt = conics[0].fPts[0]; - addPt(pt); + forceMoveTo ? this->moveTo(pt) : this->lineTo(pt); for (int i = 0; i < count; ++i) { this->conicTo(conics[i].fPts[1], conics[i].fPts[2], conics[i].fW); } } else { - addPt(singlePt); + forceMoveTo ? this->moveTo(singlePt) : this->lineTo(singlePt); } } @@ -3352,20 +3339,6 @@ bool SkPathPriv::IsSimpleClosedRect(const SkPath& path, SkRect* rect, SkPath::Di return true; } -bool SkPathPriv::DrawArcIsConvex(SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect) { - if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) { - // This gets converted to an oval. - return true; - } - if (useCenter) { - // This is a pie wedge. It's convex if the angle is <= 180. - return SkScalarAbs(sweepAngle) <= 180.f; - } - // When the angle exceeds 360 this wraps back on top of itself. Otherwise it is a circle clipped - // to a secant, i.e. convex. - return SkScalarAbs(sweepAngle) <= 360.f; -} - void SkPathPriv::CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect) { SkASSERT(!oval.isEmpty()); @@ -3376,15 +3349,11 @@ void SkPathPriv::CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar st path->setFillType(SkPath::kWinding_FillType); if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) { path->addOval(oval); - SkASSERT(path->isConvex() && DrawArcIsConvex(sweepAngle, false, isFillNoPathEffect)); return; } if (useCenter) { path->moveTo(oval.centerX(), oval.centerY()); } - auto firstDir = - sweepAngle > 0 ? SkPathPriv::kCW_FirstDirection : SkPathPriv::kCCW_FirstDirection; - bool convex = DrawArcIsConvex(sweepAngle, useCenter, isFillNoPathEffect); // Arc to mods at 360 and drawArc is not supposed to. bool forceMoveTo = !useCenter; while (sweepAngle <= -360.f) { @@ -3407,8 +3376,6 @@ void SkPathPriv::CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar st if (useCenter) { path->close(); } - path->setConvexity(convex ? SkPath::kConvex_Convexity : SkPath::kConcave_Convexity); - path->fFirstDirection.store(firstDir); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPathPriv.h b/src/core/SkPathPriv.h index 3ee1f83d06..ede79f60d9 100644 --- a/src/core/SkPathPriv.h +++ b/src/core/SkPathPriv.h @@ -105,12 +105,6 @@ public: static void CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect); - /** - * Determines whether an arc produced by CreateDrawArcPath will be convex. Assumes a non-empty - * oval. - */ - static bool DrawArcIsConvex(SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect); - /** * Returns a C++11-iterable object that traverses a path's verbs in order. e.g: * diff --git a/src/core/SkStrokeRec.cpp b/src/core/SkStrokeRec.cpp index 03678680a5..7e667bc668 100644 --- a/src/core/SkStrokeRec.cpp +++ b/src/core/SkStrokeRec.cpp @@ -136,7 +136,6 @@ void SkStrokeRec::applyToPaint(SkPaint* paint) const { } static inline SkScalar get_inflation_bounds(SkPaint::Join join, - SkPaint::Cap cap, SkScalar strokeWidth, SkScalar miterLimit) { if (strokeWidth < 0) { // fill @@ -146,25 +145,20 @@ static inline SkScalar get_inflation_bounds(SkPaint::Join join, } // since we're stroked, outset the rect by the radius (and join type) SkScalar radius = SkScalarHalf(strokeWidth); - SkScalar inflation = radius; if (SkPaint::kMiter_Join == join) { if (miterLimit > SK_Scalar1) { - inflation *= miterLimit; + radius *= miterLimit; } } - // A square cap at a 45 degree angle can add sqrt(2)*radius. - if (SkPaint::kSquare_Cap == cap) { - inflation = SkTMax(inflation, radius * SK_ScalarSqrt2); - } - return inflation; + return radius; } SkScalar SkStrokeRec::getInflationRadius() const { - return get_inflation_bounds((SkPaint::Join)fJoin, (SkPaint::Cap)fCap, fWidth, fMiterLimit); + return get_inflation_bounds((SkPaint::Join)fJoin, fWidth, fMiterLimit); } SkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) { SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth(); - return get_inflation_bounds(paint.getStrokeJoin(), paint.getStrokeCap(), width, - paint.getStrokeMiter()); + return get_inflation_bounds(paint.getStrokeJoin(), width, paint.getStrokeMiter()); + } diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 8ee341eb7f..e26ec9018b 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1353,9 +1353,10 @@ void GrRenderTargetContext::drawArc(const GrClip& clip, return; } } - this->drawShapeUsingPathRenderer( - clip, std::move(paint), aa, viewMatrix, - GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style)); + SkPath path; + SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter, + style.isSimpleFill()); + this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path, style)); } void GrRenderTargetContext::drawImageLattice(const GrClip& clip, diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp index 4cab0188d9..2d2bccbc0f 100644 --- a/src/gpu/GrShape.cpp +++ b/src/gpu/GrShape.cpp @@ -18,9 +18,6 @@ GrShape& GrShape::operator=(const GrShape& that) { case Type::kRRect: fRRectData = that.fRRectData; break; - case Type::kArc: - fArcData = that.fArcData; - break; case Type::kLine: fLineData = that.fLineData; break; @@ -85,14 +82,6 @@ GrShape GrShape::MakeFilled(const GrShape& original, FillInversion inversion) { result.fRRectData.fStart = kDefaultRRectStart; result.fRRectData.fInverted = is_inverted(original.fRRectData.fInverted, inversion); break; - case Type::kArc: - result.fType = original.fType; - result.fArcData.fOval = original.fArcData.fOval; - result.fArcData.fStartAngleDegrees = original.fArcData.fStartAngleDegrees; - result.fArcData.fSweepAngleDegrees = original.fArcData.fSweepAngleDegrees; - result.fArcData.fUseCenter = original.fArcData.fUseCenter; - result.fArcData.fInverted = is_inverted(original.fArcData.fInverted, inversion); - break; case Type::kLine: // Lines don't fill. if (is_inverted(original.fLineData.fInverted, inversion)) { @@ -155,9 +144,6 @@ SkRect GrShape::bounds() const { } case Type::kRRect: return fRRectData.fRRect.getBounds(); - case Type::kArc: - // Could make this less conservative by looking at angles. - return fArcData.fOval; case Type::kPath: return this->path().getBounds(); } @@ -229,13 +215,9 @@ int GrShape::unstyledKeySize() const { return 1; case Type::kRRect: SkASSERT(!fInheritedKey.count()); - GR_STATIC_ASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); + SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); // + 1 for the direction, start index, and inverseness. return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; - case Type::kArc: - SkASSERT(!fInheritedKey.count()); - GR_STATIC_ASSERT(0 == sizeof(fArcData) % sizeof(uint32_t)); - return sizeof(fArcData) / sizeof(uint32_t); case Type::kLine: GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint)); // 4 for the end points and 1 for the inverseness @@ -278,10 +260,6 @@ void GrShape::writeUnstyledKey(uint32_t* key) const { *key++ |= fRRectData.fStart; SkASSERT(fRRectData.fStart < 8); break; - case Type::kArc: - memcpy(key, &fArcData, sizeof(fArcData)); - key += sizeof(fArcData) / sizeof(uint32_t); - break; case Type::kLine: memcpy(key, fLineData.fPts, 2 * sizeof(SkPoint)); key += 4; @@ -371,20 +349,6 @@ void GrShape::addGenIDChangeListener(SkPathRef::GenIDChangeListener* listener) c } } -GrShape GrShape::MakeArc(const SkRect& oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, - bool useCenter, const GrStyle& style) { - GrShape result; - result.changeType(Type::kArc); - result.fArcData.fOval = oval; - result.fArcData.fStartAngleDegrees = startAngleDegrees; - result.fArcData.fSweepAngleDegrees = sweepAngleDegrees; - result.fArcData.fUseCenter = useCenter; - result.fArcData.fInverted = false; - result.fStyle = style; - result.attemptToSimplifyArc(); - return result; -} - GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr; this->initType(that.fType, thatPath); @@ -396,9 +360,6 @@ GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { case Type::kRRect: fRRectData = that.fRRectData; break; - case Type::kArc: - fArcData = that.fArcData; - break; case Type::kLine: fLineData = that.fLineData; break; @@ -627,7 +588,6 @@ void GrShape::attemptToSimplifyRRect() { } else if (fStyle.isDashed()) { // Dashing ignores the inverseness (currently). skbug.com/5421 fRRectData.fInverted = false; - // Possible TODO here: Check whether the dash results in a single arc or line. } // Turn a stroke-and-filled miter rect into a filled rect. TODO: more rrect stroke shortcuts. if (!fStyle.hasPathEffect() && @@ -680,46 +640,6 @@ void GrShape::attemptToSimplifyLine() { } } -void GrShape::attemptToSimplifyArc() { - SkASSERT(fType == Type::kArc); - SkASSERT(!fArcData.fInverted); - if (fArcData.fOval.isEmpty() || !fArcData.fSweepAngleDegrees) { - this->changeType(Type::kEmpty); - return; - } - - // Assuming no path effect, a filled, stroked, hairline, or stroke-and-filled arc that traverses - // the full circle and doesn't use the center point is an oval. Unless it has square or round - // caps. They may protrude out of the oval. Round caps can't protrude out of a circle but we're - // ignoring that for now. - if (fStyle.isSimpleFill() || (!fStyle.pathEffect() && !fArcData.fUseCenter && - fStyle.strokeRec().getCap() == SkPaint::kButt_Cap)) { - if (fArcData.fSweepAngleDegrees >= 360.f || fArcData.fSweepAngleDegrees <= -360.f) { - auto oval = fArcData.fOval; - this->changeType(Type::kRRect); - this->fRRectData.fRRect.setOval(oval); - this->fRRectData.fDir = kDefaultRRectDir; - this->fRRectData.fStart = kDefaultRRectStart; - this->fRRectData.fInverted = false; - return; - } - } - if (!fStyle.pathEffect()) { - // Canonicalize the arc such that the start is always in [0, 360) and the sweep is always - // positive. - if (fArcData.fSweepAngleDegrees < 0) { - fArcData.fStartAngleDegrees = fArcData.fStartAngleDegrees + fArcData.fSweepAngleDegrees; - fArcData.fSweepAngleDegrees = -fArcData.fSweepAngleDegrees; - } - } - if (this->fArcData.fStartAngleDegrees < 0 || this->fArcData.fStartAngleDegrees >= 360.f) { - this->fArcData.fStartAngleDegrees = SkScalarMod(this->fArcData.fStartAngleDegrees, 360.f); - } - // Possible TODOs here: Look at whether dash pattern results in a single dash and convert to - // non-dashed stroke. Stroke and fill can be fill if circular and no path effect. Just stroke - // could as well if the stroke fills the center. -} - bool GrShape::attemptToSimplifyStrokedLineToRRect() { SkASSERT(Type::kLine == fType); SkASSERT(fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style); diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h index 36402330ce..99579ba4c3 100644 --- a/src/gpu/GrShape.h +++ b/src/gpu/GrShape.h @@ -116,9 +116,6 @@ public: this->attemptToSimplifyRRect(); } - static GrShape MakeArc(const SkRect& oval, SkScalar startAngleDegrees, - SkScalar sweepAngleDegrees, bool useCenter, const GrStyle& style); - GrShape(const GrShape&); GrShape& operator=(const GrShape& that); @@ -212,16 +209,6 @@ public: out->setFillType(kDefaultPathFillType); } break; - case Type::kArc: - SkPathPriv::CreateDrawArcPath(out, fArcData.fOval, fArcData.fStartAngleDegrees, - fArcData.fSweepAngleDegrees, fArcData.fUseCenter, - fStyle.isSimpleFill()); - if (fArcData.fInverted) { - out->setFillType(kDefaultPathInverseFillType); - } else { - out->setFillType(kDefaultPathFillType); - } - break; case Type::kLine: out->reset(); out->moveTo(fLineData.fPts[0]); @@ -269,10 +256,6 @@ public: return true; case Type::kRRect: return true; - case Type::kArc: - return SkPathPriv::DrawArcIsConvex(fArcData.fSweepAngleDegrees, - SkToBool(fArcData.fUseCenter), - fStyle.isSimpleFill()); case Type::kLine: return true; case Type::kPath: @@ -299,9 +282,6 @@ public: case Type::kRRect: ret = fRRectData.fInverted; break; - case Type::kArc: - ret = fArcData.fInverted; - break; case Type::kLine: ret = fLineData.fInverted; break; @@ -340,8 +320,6 @@ public: return true; case Type::kRRect: return true; - case Type::kArc: - return fArcData.fUseCenter; case Type::kLine: return false; case Type::kPath: @@ -365,11 +343,6 @@ public: return SkPath::kLine_SegmentMask; } return SkPath::kLine_SegmentMask | SkPath::kConic_SegmentMask; - case Type::kArc: - if (fArcData.fUseCenter) { - return SkPath::kConic_SegmentMask | SkPath::kLine_SegmentMask; - } - return SkPath::kConic_SegmentMask; case Type::kLine: return SkPath::kLine_SegmentMask; case Type::kPath: @@ -414,7 +387,6 @@ private: kEmpty, kInvertedEmpty, kRRect, - kArc, kLine, kPath, }; @@ -466,7 +438,6 @@ private: void attemptToSimplifyPath(); void attemptToSimplifyRRect(); void attemptToSimplifyLine(); - void attemptToSimplifyArc(); bool attemptToSimplifyStrokedLineToRRect(); @@ -523,33 +494,26 @@ private: return kPathRRectStartIdx; } + Type fType; union { struct { - SkRRect fRRect; - SkPath::Direction fDir; - unsigned fStart; - bool fInverted; + SkRRect fRRect; + SkPath::Direction fDir; + unsigned fStart; + bool fInverted; } fRRectData; struct { - SkRect fOval; - SkScalar fStartAngleDegrees; - SkScalar fSweepAngleDegrees; - int16_t fUseCenter; - int16_t fInverted; - } fArcData; - struct { - SkPath fPath; + SkPath fPath; // Gen ID of the original path (fPath may be modified) - int32_t fGenID; + int32_t fGenID; } fPathData; struct { - SkPoint fPts[2]; - bool fInverted; + SkPoint fPts[2]; + bool fInverted; } fLineData; }; - GrStyle fStyle; - SkTLazy fInheritedPathForListeners; + GrStyle fStyle; + SkTLazy fInheritedPathForListeners; SkAutoSTArray<8, uint32_t> fInheritedKey; - Type fType; }; #endif diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp index a53dad8517..e8ec08785f 100644 --- a/tests/GrShapeTest.cpp +++ b/tests/GrShapeTest.cpp @@ -60,7 +60,7 @@ static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds) // 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; + static constexpr int kTol = 0; GR_STATIC_ASSERT(kRes % 4 == 0); SkImageInfo info = SkImageInfo::MakeA8(kRes, kRes); sk_sp surface = SkSurface::MakeRaster(info); @@ -389,34 +389,6 @@ 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 }; @@ -2149,10 +2121,6 @@ DEF_TEST(GrShape, reporter) { 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); @@ -2253,80 +2221,4 @@ DEF_TEST(GrShape, reporter) { 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 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); - } -} - #endif