diff options
author | bsalomon <bsalomon@google.com> | 2016-06-28 11:56:42 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-28 11:56:42 -0700 |
commit | 0a0f67ececbdf1a7f81296ed0d2cb9e3bc00e4dc (patch) | |
tree | f49e73525e56c6e6d0dcfc68f1eeba895920137b /src | |
parent | 635df95a9a25c66959f76b4bbb594b75333ded21 (diff) |
Make lines a special case in GrShape
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2108523002
Committed: https://skia.googlesource.com/skia/+/c62318c748a1907649bd75382c4f4fd10533f2b3
Review-Url: https://codereview.chromium.org/2108523002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrShape.cpp | 89 | ||||
-rw-r--r-- | src/gpu/GrShape.h | 48 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.cpp | 3 | ||||
-rw-r--r-- | src/gpu/batches/GrAADistanceFieldPathRenderer.cpp | 3 | ||||
-rw-r--r-- | src/gpu/batches/GrDashLinePathRenderer.cpp | 7 |
6 files changed, 119 insertions, 34 deletions
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 7ee4e620e5..eec1389a81 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -976,6 +976,9 @@ void GrDrawContext::internalDrawPath(const GrClip& clip, : GrPathRendererChain::kColor_DrawType; GrShape shape(path, style); + if (shape.isEmpty()) { + return; + } GrPathRenderer::CanDrawPathArgs canDrawArgs; canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps(); canDrawArgs.fViewMatrix = &viewMatrix; diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp index 45ddb77778..5ffd32d46d 100644 --- a/src/gpu/GrShape.cpp +++ b/src/gpu/GrShape.cpp @@ -14,10 +14,10 @@ GrShape& GrShape::operator=(const GrShape& that) { case Type::kEmpty: break; case Type::kRRect: - fRRectData.fRRect = that.fRRectData.fRRect; - fRRectData.fDir = that.fRRectData.fDir; - fRRectData.fStart = that.fRRectData.fStart; - fRRectData.fInverted = that.fRRectData.fInverted; + fRRectData = that.fRRectData; + break; + case Type::kLine: + fLineData = that.fLineData; break; case Type::kPath: fPathData.fGenID = that.fPathData.fGenID; @@ -29,11 +29,29 @@ GrShape& GrShape::operator=(const GrShape& that) { return *this; } -const SkRect& GrShape::bounds() const { +SkRect GrShape::bounds() const { static constexpr SkRect kEmpty = SkRect::MakeEmpty(); switch (fType) { case Type::kEmpty: return kEmpty; + case Type::kLine: { + SkRect bounds; + if (fLineData.fPts[0].fX < fLineData.fPts[1].fX) { + bounds.fLeft = fLineData.fPts[0].fX; + bounds.fRight = fLineData.fPts[1].fX; + } else { + bounds.fLeft = fLineData.fPts[1].fX; + bounds.fRight = fLineData.fPts[0].fX; + } + if (fLineData.fPts[0].fY < fLineData.fPts[1].fY) { + bounds.fTop = fLineData.fPts[0].fY; + bounds.fBottom = fLineData.fPts[1].fY; + } else { + bounds.fTop = fLineData.fPts[1].fY; + bounds.fBottom = fLineData.fPts[0].fY; + } + return bounds; + } case Type::kRRect: return fRRectData.fRRect.getBounds(); case Type::kPath: @@ -43,12 +61,13 @@ const SkRect& GrShape::bounds() const { return kEmpty; } -void GrShape::styledBounds(SkRect* bounds) const { +SkRect GrShape::styledBounds() const { if (Type::kEmpty == fType && !fStyle.hasNonDashPathEffect()) { - *bounds = SkRect::MakeEmpty(); - } else { - fStyle.adjustBounds(bounds, this->bounds()); + return SkRect::MakeEmpty(); } + SkRect bounds; + fStyle.adjustBounds(&bounds, this->bounds()); + return bounds; } int GrShape::unstyledKeySize() const { @@ -63,6 +82,10 @@ int GrShape::unstyledKeySize() const { SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t)); // + 1 for the direction, start index, and inverseness. return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; + case Type::kLine: + GR_STATIC_ASSERT(2 * sizeof(uint32_t) == sizeof(SkPoint)); + // 4 for the end points and 1 for the inverseness + return 5; case Type::kPath: if (0 == fPathData.fGenID) { return -1; @@ -94,6 +117,11 @@ void GrShape::writeUnstyledKey(uint32_t* key) const { *key++ |= fRRectData.fStart; SkASSERT(fRRectData.fStart < 8); break; + case Type::kLine: + memcpy(key, fLineData.fPts, 2 * sizeof(SkPoint)); + key += 4; + *key++ = fLineData.fInverted ? 1 : 0; + break; case Type::kPath: SkASSERT(fPathData.fGenID); *key++ = fPathData.fGenID; @@ -159,10 +187,10 @@ GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { case Type::kEmpty: break; case Type::kRRect: - fRRectData.fRRect = that.fRRectData.fRRect; - fRRectData.fDir = that.fRRectData.fDir; - fRRectData.fStart = that.fRRectData.fStart; - fRRectData.fInverted = that.fRRectData.fInverted; + fRRectData = that.fRRectData; + break; + case Type::kLine: + fLineData = that.fLineData; break; case Type::kPath: fPathData.fGenID = that.fPathData.fGenID; @@ -266,8 +294,14 @@ void GrShape::attemptToSimplifyPath() { SkPath::Direction rrectDir; unsigned rrectStart; bool inverted = this->path().isInverseFillType(); + SkPoint pts[2]; if (this->path().isEmpty()) { this->changeType(Type::kEmpty); + } else if (this->path().isLine(pts)) { + this->changeType(Type::kLine); + fLineData.fPts[0] = pts[0]; + fLineData.fPts[1] = pts[1]; + fLineData.fInverted = inverted; } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { this->changeType(Type::kRRect); fRRectData.fRRect = rrect; @@ -313,6 +347,8 @@ void GrShape::attemptToSimplifyPath() { fInheritedKey.reset(0); if (Type::kRRect == fType) { this->attemptToSimplifyRRect(); + } else if (Type::kLine == fType) { + this->attemptToSimplifyLine(); } } else { if (fInheritedKey.count() || this->path().isVolatile()) { @@ -321,13 +357,8 @@ void GrShape::attemptToSimplifyPath() { fPathData.fGenID = this->path().getGenerationID(); } if (this->style().isSimpleFill()) { - // Filled paths are treated as though all their contours were closed. - // Since SkPath doesn't track individual contours, this will only close the last. :( - // There is no point in closing lines, though, since they loose their line-ness. - if (!this->path().isLine(nullptr)) { - this->path().close(); - this->path().setIsVolatile(true); - } + this->path().close(); + this->path().setIsVolatile(true); } if (!this->style().hasNonDashPathEffect()) { if (this->style().strokeRec().getStyle() == SkStrokeRec::kStroke_Style || @@ -368,3 +399,21 @@ void GrShape::attemptToSimplifyRRect() { fRRectData.fInverted = false; } } + +void GrShape::attemptToSimplifyLine() { + if (fStyle.isSimpleFill() && !fLineData.fInverted) { + this->changeType(Type::kEmpty); + } else { + // Only path effects could care about the order of the points. Otherwise canonicalize + // the point order + if (!fStyle.hasPathEffect()) { + SkPoint* pts = fLineData.fPts; + if (pts[1].fY < pts[0].fY || (pts[1].fY == pts[0].fY && pts[1].fX < pts[0].fX)) { + SkTSwap(pts[0], pts[1]); + } + } else if (fStyle.isDashed()) { + // Dashing ignores inverseness. + fLineData.fInverted = false; + } + } +} diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h index 87ee26e173..8f3be58702 100644 --- a/src/gpu/GrShape.h +++ b/src/gpu/GrShape.h @@ -152,12 +152,19 @@ public: * If the unstyled shape is a straight line segment, returns true and sets pts to the endpoints. * An inverse filled line path is still considered a line. */ - bool asLine(SkPoint pts[2]) const { - if (fType != Type::kPath) { - return false; - } - return this->path().isLine(pts); - } + bool asLine(SkPoint pts[2], bool* inverted) const { + if (fType != Type::kLine) { + return false; + } + if (pts) { + pts[0] = fLineData.fPts[0]; + pts[1] = fLineData.fPts[1]; + } + if (inverted) { + *inverted = fLineData.fInverted; + } + return true; + } /** Returns the unstyled geometry as a path. */ void asPath(SkPath* out) const { @@ -175,6 +182,16 @@ public: out->setFillType(kDefaultPathFillType); } break; + case Type::kLine: + out->reset(); + out->moveTo(fLineData.fPts[0]); + out->lineTo(fLineData.fPts[1]); + if (fLineData.fInverted) { + out->setFillType(kDefaultPathInverseFillType); + } else { + out->setFillType(kDefaultPathFillType); + } + break; case Type::kPath: *out = this->path(); break; @@ -191,13 +208,13 @@ public: * Gets the bounds of the geometry without reflecting the shape's styling. This ignores * the inverse fill nature of the geometry. */ - const SkRect& bounds() const; + SkRect bounds() const; /** * Gets the bounds of the geometry reflecting the shape's styling (ignoring inverse fill * status). */ - void styledBounds(SkRect* bounds) const; + SkRect styledBounds() const; /** * Is this shape known to be convex, before styling is applied. An unclosed but otherwise @@ -210,6 +227,8 @@ public: return true; case Type::kRRect: return true; + case Type::kLine: + return true; case Type::kPath: // SkPath.isConvex() really means "is this path convex were it to be closed" and // thus doesn't give the correct answer for stroked paths, hence we also check @@ -231,6 +250,9 @@ public: case Type::kRRect: ret = fRRectData.fInverted; break; + case Type::kLine: + ret = fLineData.fInverted; + break; case Type::kPath: ret = this->path().isInverseFillType(); break; @@ -264,6 +286,8 @@ public: return true; case Type::kRRect: return true; + case Type::kLine: + return false; case Type::kPath: // SkPath doesn't keep track of the closed status of each contour. return SkPathPriv::IsClosedSingleContour(this->path()); @@ -282,6 +306,8 @@ public: return SkPath::kLine_SegmentMask; } return SkPath::kLine_SegmentMask | SkPath::kConic_SegmentMask; + case Type::kLine: + return SkPath::kLine_SegmentMask; case Type::kPath: return this->path().getSegmentMasks(); } @@ -307,6 +333,7 @@ private: enum class Type { kEmpty, kRRect, + kLine, kPath, }; @@ -356,6 +383,7 @@ private: void attemptToSimplifyPath(); void attemptToSimplifyRRect(); + void attemptToSimplifyLine(); // Defaults to use when there is no distinction between even/odd and winding fills. static constexpr SkPath::FillType kDefaultPathFillType = SkPath::kEvenOdd_FillType; @@ -420,6 +448,10 @@ private: // Gen ID of the original path (fPath may be modified) int32_t fGenID; } fPathData; + struct { + SkPoint fPts[2]; + bool fInverted; + } fLineData; }; GrStyle fStyle; SkAutoSTArray<8, uint32_t> fInheritedKey; diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index 983bd20cbe..45a4b78b18 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -38,8 +38,7 @@ bool get_shape_and_clip_bounds(int width, int height, *devShapeBounds = SkIRect::MakeWH(width, height); return false; } - SkRect shapeBounds; - shape.styledBounds(&shapeBounds); + SkRect shapeBounds = shape.styledBounds(); if (!shapeBounds.isEmpty()) { SkRect shapeSBounds; matrix.mapRect(&shapeSBounds, shapeBounds); diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp index b178a68107..eb6a67dc20 100644 --- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp @@ -109,8 +109,7 @@ bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP // the goal is to accelerate rendering of lots of small paths that may be scaling SkScalar maxScale = args.fViewMatrix->getMaxScale(); - SkRect bounds; - args.fShape->styledBounds(&bounds); + SkRect bounds = args.fShape->styledBounds(); SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; diff --git a/src/gpu/batches/GrDashLinePathRenderer.cpp b/src/gpu/batches/GrDashLinePathRenderer.cpp index 8dba7b94da..e7ef2402a9 100644 --- a/src/gpu/batches/GrDashLinePathRenderer.cpp +++ b/src/gpu/batches/GrDashLinePathRenderer.cpp @@ -13,7 +13,10 @@ bool GrDashLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { SkPoint pts[2]; - if (args.fShape->style().isDashed() && args.fShape->asLine(pts)) { + bool inverted; + if (args.fShape->style().isDashed() && args.fShape->asLine(pts, &inverted)) { + // We should never have an inverse dashed case. + SkASSERT(!inverted); return GrDashingEffect::CanDrawDashLine(pts, args.fShape->style(), *args.fViewMatrix); } return false; @@ -34,7 +37,7 @@ bool GrDashLinePathRenderer::onDrawPath(const DrawPathArgs& args) { aaMode = GrDashingEffect::AAMode::kNone; } SkPoint pts[2]; - SkAssertResult(args.fShape->asLine(pts)); + SkAssertResult(args.fShape->asLine(pts, nullptr)); SkAutoTUnref<GrDrawBatch> batch(GrDashingEffect::CreateDashLineBatch(args.fColor, *args.fViewMatrix, pts, |