diff options
author | Brian Salomon <bsalomon@google.com> | 2018-04-25 11:21:39 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-04-25 18:54:07 +0000 |
commit | 8a98bc96748d1bdaf9c2d8cfa0b672e3a035973d (patch) | |
tree | f3d3147435661928de22456a7762d3dc20a2c71e /src/gpu/GrShape.cpp | |
parent | cfd650e43ff1da223129aac36f222daaf1cf61e5 (diff) |
Revert "Revert "Add arcs as a specialized geometry to GrShape.""
This reverts commit af88ec37124846a0168a4ab061bf10cc6030c2d6.
Bug: skia:7794
Change-Id: I2d0e1d7b4e025481241d823b09f5de5d0f1a13eb
Reviewed-on: https://skia-review.googlesource.com/123627
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu/GrShape.cpp')
-rw-r--r-- | src/gpu/GrShape.cpp | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp index 2d2bccbc0f..189b57be80 100644 --- a/src/gpu/GrShape.cpp +++ b/src/gpu/GrShape.cpp @@ -18,6 +18,9 @@ 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; @@ -82,6 +85,14 @@ 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)) { @@ -144,6 +155,9 @@ 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(); } @@ -215,9 +229,13 @@ int GrShape::unstyledKeySize() const { return 1; case Type::kRRect: SkASSERT(!fInheritedKey.count()); - SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); + GR_STATIC_ASSERT(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 @@ -260,6 +278,10 @@ 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; @@ -349,6 +371,29 @@ void GrShape::addGenIDChangeListener(SkPathRef::GenIDChangeListener* listener) c } } +GrShape GrShape::MakeArc(const SkRect& oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, + bool useCenter, const GrStyle& style) { +#ifdef SK_DISABLE_ARC_TO_LINE_TO_CHECK + // When this flag is set the segment mask of the path won't match GrShape's segment mask for + // paths. Represent this shape as a path. + SkPath path; + SkPathPriv::CreateDrawArcPath(&path, oval, startAngleDegrees, sweepAngleDegrees, useCenter, + style.isSimpleFill()); + return GrShape(path, style); +#else + 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; +#endif +} + GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr; this->initType(that.fType, thatPath); @@ -360,6 +405,9 @@ 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; @@ -588,6 +636,7 @@ 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() && @@ -640,6 +689,46 @@ 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); |