Chromium Code Reviews| Index: src/gpu/batches/GrAAConvexTessellator.cpp |
| diff --git a/src/gpu/batches/GrAAConvexTessellator.cpp b/src/gpu/batches/GrAAConvexTessellator.cpp |
| index af3ce89257d890132db64b5767bf120fd3b5540c..528114a2753e28db8ceea52da2320c1c0bd5f7f8 100644 |
| --- a/src/gpu/batches/GrAAConvexTessellator.cpp |
| +++ b/src/gpu/batches/GrAAConvexTessellator.cpp |
| @@ -32,11 +32,17 @@ static const SkScalar kRoundCapThreshold = 0.8f; |
| // dot product above which we consider two adjacent curves to be part of the "same" curve |
| static const SkScalar kCurveConnectionThreshold = 0.8f; |
| -static SkScalar intersect(const SkPoint& p0, const SkPoint& n0, |
| - const SkPoint& p1, const SkPoint& n1) { |
| +static bool intersect(const SkPoint& p0, const SkPoint& n0, |
| + const SkPoint& p1, const SkPoint& n1, |
| + SkScalar* t) { |
| const SkPoint v = p1 - p0; |
| SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX; |
| - return (v.fX * n1.fY - v.fY * n1.fX) / perpDot; |
| + if (SkScalarNearlyZero(perpDot)) { |
| + return true; |
|
ethannicholas
2016/09/06 20:34:05
The return value of this function seems backward t
robertphillips
2016/09/06 20:47:06
Haha - good point. Fixed.
|
| + } |
| + *t = (v.fX * n1.fY - v.fY * n1.fX) / perpDot; |
| + SkASSERT(SkScalarIsFinite(*t)); |
| + return false; |
| } |
| // This is a special case version of intersect where we have the vector |
| @@ -218,7 +224,44 @@ bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { |
| SkScalar coverage = 1.0f; |
| SkScalar scaleFactor = 0.0f; |
| - if (fStrokeWidth >= 0.0f) { |
| + |
| + if (SkStrokeRec::kStrokeAndFill_Style == fStyle) { |
| + SkASSERT(m.isSimilarity()); |
| + scaleFactor = m.getMaxScale(); // x and y scale are the same |
| + SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; |
| + Ring outerStrokeAndAARing; |
| + this->createOuterRing(fInitialRing, |
| + effectiveStrokeWidth / 2 + kAntialiasingRadius, 0.0, |
| + &outerStrokeAndAARing); |
| + |
| + // discard all the triangles added between the originating ring and the new outer ring |
| + fIndices.rewind(); |
| + |
| + outerStrokeAndAARing.init(*this); |
| + |
| + outerStrokeAndAARing.makeOriginalRing(); |
| + |
| + // Add the outer stroke ring's normals to the originating ring's normals |
| + // so it can also act as an originating ring |
| + fNorms.setReserve(fNorms.count() + outerStrokeAndAARing.numPts()); |
| + for (int i = 0; i < outerStrokeAndAARing.numPts(); ++i) { |
| + fNorms.push(outerStrokeAndAARing.norm(i)); |
| + } |
| + |
| + // the bisectors are only needed for the computation of the outer ring |
| + fBisectors.rewind(); |
| + |
| + Ring* insetAARing; |
| + this->createInsetRings(outerStrokeAndAARing, |
| + 0.0f, 0.0f, 2*kAntialiasingRadius, 1.0f, |
| + &insetAARing); |
| + |
| + SkDEBUGCODE(this->validate();) |
| + return true; |
| + } |
| + |
| + if (SkStrokeRec::kStroke_Style == fStyle) { |
| + SkASSERT(fStrokeWidth >= 0.0f); |
| SkASSERT(m.isSimilarity()); |
| scaleFactor = m.getMaxScale(); // x and y scale are the same |
| SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; |
| @@ -235,15 +278,16 @@ bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { |
| // the bisectors are only needed for the computation of the outer ring |
| fBisectors.rewind(); |
| - if (fStrokeWidth >= 0.0f && fInitialRing.numPts() > 2) { |
| + if (SkStrokeRec::kStroke_Style == fStyle && fInitialRing.numPts() > 2) { |
| + SkASSERT(fStrokeWidth >= 0.0f); |
| SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; |
| Ring* insetStrokeRing; |
| SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius; |
| if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, coverage, |
| - &insetStrokeRing)) { |
| + &insetStrokeRing)) { |
| Ring* insetAARing; |
| this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, strokeDepth + |
| - kAntialiasingRadius * 2, 0.0f, &insetAARing); |
| + kAntialiasingRadius * 2, 0.0f, &insetAARing); |
| } |
| } else { |
| Ring* insetAARing; |
| @@ -390,7 +434,7 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat |
| this->computeBisectors(); |
| } else if (this->numPts() == 2) { |
| // We've got two points, so we're degenerate. |
| - if (fStrokeWidth < 0.0f) { |
| + if (fStyle == SkStrokeRec::kFill_Style) { |
| // it's a fill, so we don't need to worry about degenerate paths |
| return false; |
| } |
| @@ -586,7 +630,7 @@ void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar o |
| // Something went wrong in the creation of the next ring. If we're filling the shape, just go ahead |
| // and fan it. |
| void GrAAConvexTessellator::terminate(const Ring& ring) { |
| - if (fStrokeWidth < 0.0f) { |
| + if (fStyle != SkStrokeRec::kStroke_Style) { |
| this->fanRing(ring); |
| } |
| } |
| @@ -616,8 +660,14 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing |
| for (int cur = 0; cur < lastRing.numPts(); ++cur) { |
| int next = (cur + 1) % lastRing.numPts(); |
| - SkScalar t = intersect(this->point(lastRing.index(cur)), lastRing.bisector(cur), |
| - this->point(lastRing.index(next)), lastRing.bisector(next)); |
| + |
| + SkScalar t; |
| + bool parallel = intersect(this->point(lastRing.index(cur)), lastRing.bisector(cur), |
| + this->point(lastRing.index(next)), lastRing.bisector(next), |
| + &t); |
| + if (parallel) { |
| + continue; |
| + } |
| SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur)); |
| if (minDist > dist) { |
| @@ -745,8 +795,8 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing |
| this->addTri(lastRing.index(i), dst[next], dst[i]); |
| } |
| - if (done && fStrokeWidth < 0.0f) { |
| - // fill |
| + if (done && fStyle != SkStrokeRec::kStroke_Style) { |
| + // fill or stroke-and-fill |
| this->fanRing(*nextRing); |
| } |
| @@ -860,7 +910,7 @@ void GrAAConvexTessellator::lineTo(SkPoint p, CurveState curve) { |
| return; |
| } |
| } |
| - SkScalar initialRingCoverage = fStrokeWidth < 0.0f ? 0.5f : 1.0f; |
| + SkScalar initialRingCoverage = (SkStrokeRec::kFill_Style == fStyle) ? 0.5f : 1.0f; |
| this->addPt(p, 0.0f, initialRingCoverage, false, curve); |
| if (this->numPts() > 1) { |
| *fNorms.push() = fPts.top() - fPts[fPts.count()-2]; |