Chromium Code Reviews| Index: src/gpu/GrAAFlatteningConvexTessellator.cpp | 
| diff --git a/src/gpu/GrAAConvexTessellator.cpp b/src/gpu/GrAAFlatteningConvexTessellator.cpp | 
| similarity index 73% | 
| copy from src/gpu/GrAAConvexTessellator.cpp | 
| copy to src/gpu/GrAAFlatteningConvexTessellator.cpp | 
| index 5a1e4c2dfedcc56671ca4e80ddb01a34ba5b1919..8aca476d6c45e98e468f222455da8f09d73bc58c 100644 | 
| --- a/src/gpu/GrAAConvexTessellator.cpp | 
| +++ b/src/gpu/GrAAFlatteningConvexTessellator.cpp | 
| @@ -5,11 +5,12 @@ | 
| * found in the LICENSE file. | 
| */ | 
| -#include "GrAAConvexTessellator.h" | 
| +#include "GrAAFlatteningConvexTessellator.h" | 
| #include "SkCanvas.h" | 
| #include "SkPath.h" | 
| #include "SkPoint.h" | 
| #include "SkString.h" | 
| +#include "GrPathUtils.h" | 
| // Next steps: | 
| // use in AAConvexPathRenderer | 
| @@ -49,21 +50,23 @@ static SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const S | 
| return SkScalarAbs(dist); | 
| } | 
| -int GrAAConvexTessellator::addPt(const SkPoint& pt, | 
| +int GrAAFlatteningConvexTessellator::addPt(const SkPoint& pt, | 
| 
 
robertphillips
2015/05/27 18:10:54
line these guys up ?
 
 | 
| SkScalar depth, | 
| - bool movable) { | 
| + bool movable, | 
| + bool isCurve) { | 
| this->validate(); | 
| int index = fPts.count(); | 
| *fPts.push() = pt; | 
| *fDepths.push() = depth; | 
| *fMovable.push() = movable; | 
| + *fIsCurve.push() = isCurve; | 
| this->validate(); | 
| return index; | 
| } | 
| -void GrAAConvexTessellator::popLastPt() { | 
| +void GrAAFlatteningConvexTessellator::popLastPt() { | 
| this->validate(); | 
| fPts.pop(); | 
| @@ -73,7 +76,7 @@ void GrAAConvexTessellator::popLastPt() { | 
| this->validate(); | 
| } | 
| -void GrAAConvexTessellator::popFirstPtShuffle() { | 
| +void GrAAFlatteningConvexTessellator::popFirstPtShuffle() { | 
| this->validate(); | 
| fPts.removeShuffle(0); | 
| @@ -83,7 +86,7 @@ void GrAAConvexTessellator::popFirstPtShuffle() { | 
| this->validate(); | 
| } | 
| -void GrAAConvexTessellator::updatePt(int index, | 
| +void GrAAFlatteningConvexTessellator::updatePt(int index, | 
| 
 
robertphillips
2015/05/27 18:10:54
line up ?
 
 | 
| const SkPoint& pt, | 
| SkScalar depth) { | 
| this->validate(); | 
| @@ -93,7 +96,7 @@ void GrAAConvexTessellator::updatePt(int index, | 
| fDepths[index] = depth; | 
| } | 
| -void GrAAConvexTessellator::addTri(int i0, int i1, int i2) { | 
| +void GrAAFlatteningConvexTessellator::addTri(int i0, int i1, int i2) { | 
| if (i0 == i1 || i1 == i2 || i2 == i0) { | 
| return; | 
| } | 
| @@ -103,7 +106,7 @@ void GrAAConvexTessellator::addTri(int i0, int i1, int i2) { | 
| *fIndices.push() = i2; | 
| } | 
| -void GrAAConvexTessellator::rewind() { | 
| +void GrAAFlatteningConvexTessellator::rewind() { | 
| fPts.rewind(); | 
| fDepths.rewind(); | 
| fMovable.rewind(); | 
| @@ -111,7 +114,7 @@ void GrAAConvexTessellator::rewind() { | 
| fNorms.rewind(); | 
| fInitialRing.rewind(); | 
| fCandidateVerts.rewind(); | 
| -#if GR_AA_CONVEX_TESSELLATOR_VIZ | 
| +#if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ | 
| fRings.rewind(); // TODO: leak in this case! | 
| #else | 
| fRings[0].rewind(); | 
| @@ -119,7 +122,7 @@ void GrAAConvexTessellator::rewind() { | 
| #endif | 
| } | 
| -void GrAAConvexTessellator::computeBisectors() { | 
| +void GrAAFlatteningConvexTessellator::computeBisectors() { | 
| fBisectors.setCount(fNorms.count()); | 
| int prev = fBisectors.count() - 1; | 
| @@ -143,11 +146,11 @@ void GrAAConvexTessellator::computeBisectors() { | 
| // The general idea here is to, conceptually, start with the original polygon and slide | 
| // the vertices along the bisectors until the first intersection. At that | 
| // point two of the edges collapse and the process repeats on the new polygon. | 
| -// The polygon state is captured in the Ring class while the GrAAConvexTessellator | 
| +// The polygon state is captured in the Ring class while the GrAAFlatteningConvexTessellator | 
| // controls the iteration. The CandidateVerts holds the formative points for the | 
| // next ring. | 
| -bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { | 
| - static const int kMaxNumRings = 8; | 
| +bool GrAAFlatteningConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { | 
| + static const int kMaxNumRings = 1; | 
| SkDEBUGCODE(fShouldCheckDepths = true;) | 
| @@ -190,7 +193,7 @@ bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { | 
| return true; | 
| } | 
| -SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const { | 
| +SkScalar GrAAFlatteningConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const { | 
| SkASSERT(edgeIdx < fNorms.count()); | 
| SkPoint v = p - fPts[edgeIdx]; | 
| @@ -201,7 +204,7 @@ SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& | 
| // Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies | 
| // along the 'bisector' from the 'startIdx'-th point. | 
| -bool GrAAConvexTessellator::computePtAlongBisector(int startIdx, | 
| +bool GrAAFlatteningConvexTessellator::computePtAlongBisector(int startIdx, | 
| 
 
robertphillips
2015/05/27 18:10:54
line up ?
 
 | 
| const SkVector& bisector, | 
| int edgeIdx, | 
| SkScalar desiredDepth, | 
| @@ -235,8 +238,7 @@ bool GrAAConvexTessellator::computePtAlongBisector(int startIdx, | 
| return true; | 
| } | 
| -bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& path) { | 
| - SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks()); | 
| +bool GrAAFlatteningConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& path) { | 
| SkASSERT(SkPath::kConvex_Convexity == path.getConvexity()); | 
| // Outer ring: 3*numPts | 
| @@ -250,8 +252,6 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat | 
| fNorms.setReserve(path.countPoints()); | 
| - SkScalar minCross = SK_ScalarMax, maxCross = -SK_ScalarMax; | 
| - | 
| // TODO: is there a faster way to extract the points from the path? Perhaps | 
| // get all the points via a new entry point, transform them all in bulk | 
| // and then walk them to find duplicates? | 
| @@ -261,38 +261,16 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat | 
| while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { | 
| switch (verb) { | 
| case SkPath::kLine_Verb: | 
| - m.mapPoints(&pts[1], 1); | 
| - if (this->numPts() > 0 && duplicate_pt(pts[1], this->lastPoint())) { | 
| - continue; | 
| - } | 
| - | 
| - SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1); | 
| - if (this->numPts() >= 2 && | 
| - abs_dist_from_line(fPts.top(), fNorms.top(), pts[1]) < kClose) { | 
| - // The old last point is on the line from the second to last to the new point | 
| - this->popLastPt(); | 
| - fNorms.pop(); | 
| - } | 
| - | 
| - this->addPt(pts[1], 0.0f, false); | 
| - if (this->numPts() > 1) { | 
| - *fNorms.push() = fPts.top() - fPts[fPts.count()-2]; | 
| - SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top()); | 
| - SkASSERT(len > 0.0f); | 
| - SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length())); | 
| - } | 
| - | 
| - if (this->numPts() >= 3) { | 
| - int cur = this->numPts()-1; | 
| - SkScalar cross = SkPoint::CrossProduct(fNorms[cur-1], fNorms[cur-2]); | 
| - maxCross = SkTMax(maxCross, cross); | 
| - minCross = SkTMin(minCross, cross); | 
| - } | 
| + lineTo(m, pts[1], false); | 
| 
 
bsalomon
2015/05/27 17:11:07
style nit, for (non-static) method calls we prefix
 
ethannicholas
2015/05/27 19:22:30
Done.
 
 | 
| break; | 
| case SkPath::kQuad_Verb: | 
| - case SkPath::kConic_Verb: | 
| + quadTo(m, pts); | 
| + break; | 
| case SkPath::kCubic_Verb: | 
| - SkASSERT(false); | 
| + cubicTo(m, pts); | 
| + break; | 
| + case SkPath::kConic_Verb: | 
| + conicTo(m, pts, iter.conicWeight()); | 
| break; | 
| case SkPath::kMove_Verb: | 
| case SkPath::kClose_Verb: | 
| @@ -344,14 +322,9 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat | 
| // Check the cross produce of the final trio | 
| SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top()); | 
| 
 
robertphillips
2015/05/27 18:10:54
Hmmm ...
 
ethannicholas
2015/05/27 19:22:30
The work to compute the min & max cross products s
 
 | 
| - maxCross = SkTMax(maxCross, cross); | 
| - minCross = SkTMin(minCross, cross); | 
| - | 
| - if (maxCross > 0.0f) { | 
| - SkASSERT(minCross >= 0.0f); | 
| + if (cross > 0.0f) { | 
| fSide = SkPoint::kRight_Side; | 
| } else { | 
| - SkASSERT(minCross <= 0.0f); | 
| fSide = SkPoint::kLeft_Side; | 
| } | 
| @@ -374,8 +347,8 @@ bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat | 
| return true; | 
| } | 
| -GrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) { | 
| -#if GR_AA_CONVEX_TESSELLATOR_VIZ | 
| +GrAAFlatteningConvexTessellator::Ring* GrAAFlatteningConvexTessellator::getNextRing(Ring* lastRing) { | 
| +#if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ | 
| Ring* ring = *fRings.push() = SkNEW(Ring); | 
| ring->setReserve(fInitialRing.numPts()); | 
| ring->rewind(); | 
| @@ -389,14 +362,14 @@ GrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) | 
| #endif | 
| } | 
| -void GrAAConvexTessellator::fanRing(const Ring& ring) { | 
| +void GrAAFlatteningConvexTessellator::fanRing(const Ring& ring) { | 
| // fan out from point 0 | 
| for (int cur = 1; cur < ring.numPts()-1; ++cur) { | 
| this->addTri(ring.index(0), ring.index(cur), ring.index(cur+1)); | 
| } | 
| } | 
| -void GrAAConvexTessellator::createOuterRing() { | 
| +void GrAAFlatteningConvexTessellator::createOuterRing() { | 
| // For now, we're only generating one outer ring (at the start). This | 
| // could be relaxed for stroking use cases. | 
| SkASSERT(0 == fIndices.count()); | 
| @@ -404,76 +377,108 @@ void GrAAConvexTessellator::createOuterRing() { | 
| const int numPts = fPts.count(); | 
| - // For each vertex of the original polygon we add three points to the | 
| - // outset polygon - one extending perpendicular to each impinging edge | 
| - // and one along the bisector. Two triangles are added for each corner | 
| - // and two are added along each edge. | 
| int prev = numPts - 1; | 
| int lastPerpIdx = -1, firstPerpIdx = -1, newIdx0, newIdx1, newIdx2; | 
| for (int cur = 0; cur < numPts; ++cur) { | 
| - // The perpendicular point for the last edge | 
| - SkPoint temp = fNorms[prev]; | 
| - temp.scale(fTargetDepth); | 
| - temp += fPts[cur]; | 
| - | 
| - // We know it isn't a duplicate of the prior point (since it and this | 
| - // one are just perpendicular offsets from the non-merged polygon points) | 
| - newIdx0 = this->addPt(temp, -fTargetDepth, false); | 
| - | 
| - // The bisector outset point | 
| - temp = fBisectors[cur]; | 
| - temp.scale(-fTargetDepth); // the bisectors point in | 
| - temp += fPts[cur]; | 
| - | 
| - // For very shallow angles all the corner points could fuse | 
| - if (duplicate_pt(temp, this->point(newIdx0))) { | 
| - newIdx1 = newIdx0; | 
| - } else { | 
| - newIdx1 = this->addPt(temp, -fTargetDepth, false); | 
| + if (fIsCurve[cur]) { | 
| + // Inside a curve, we assume that the curvature is shallow enough (due to tesselation) | 
| + // that we only need one corner point. Mathematically, the distance the corner point | 
| + // gets shifted out should depend on the angle between the two line segments (as in | 
| + // mitering), but again due to tesselation we assume that this angle is small and | 
| + // therefore the correction factor is negligible and we do not bother with it. | 
| 
 
bsalomon
2015/05/27 17:11:07
Is it reasonable to have an assert that verifies t
 
ethannicholas
2015/05/27 19:22:30
Done.
 
 | 
| + | 
| + // The bisector outset point | 
| + SkPoint temp = fBisectors[cur]; | 
| + temp.scale(-fTargetDepth); // the bisectors point in | 
| + temp += fPts[cur]; | 
| + | 
| + newIdx1 = this->addPt(temp, -fTargetDepth, false, true); | 
| + | 
| + if (0 == cur) { | 
| + // Store the index of the first perpendicular point to finish up | 
| + firstPerpIdx = newIdx1; | 
| + SkASSERT(-1 == lastPerpIdx); | 
| + } else { | 
| + // The triangles for the previous edge | 
| + this->addTri(prev, newIdx1, cur); | 
| + this->addTri(prev, lastPerpIdx, newIdx1); | 
| + } | 
| + | 
| + prev = cur; | 
| + // Track the last perpendicular outset point so we can construct the | 
| + // trailing edge triangles. | 
| + lastPerpIdx = newIdx1; | 
| } | 
| - | 
| - // The perpendicular point for the next edge. | 
| - temp = fNorms[cur]; | 
| - temp.scale(fTargetDepth); | 
| - temp += fPts[cur]; | 
| - | 
| - // For very shallow angles all the corner points could fuse. | 
| - if (duplicate_pt(temp, this->point(newIdx1))) { | 
| - newIdx2 = newIdx1; | 
| - } else { | 
| - newIdx2 = this->addPt(temp, -fTargetDepth, false); | 
| + else { | 
| + // For each vertex of the original polygon we add three points to the | 
| + // outset polygon - one extending perpendicular to each impinging edge | 
| + // and one along the bisector. Two triangles are added for each corner | 
| + // and two are added along each edge. | 
| + | 
| + // The perpendicular point for the last edge | 
| + SkPoint temp = fNorms[prev]; | 
| + temp.scale(fTargetDepth); | 
| + temp += fPts[cur]; | 
| + | 
| + // We know it isn't a duplicate of the prior point (since it and this | 
| + // one are just perpendicular offsets from the non-merged polygon points) | 
| + newIdx0 = this->addPt(temp, -fTargetDepth, false, false); | 
| + | 
| + // The bisector outset point | 
| + temp = fBisectors[cur]; | 
| + temp.scale(-fTargetDepth); // the bisectors point in | 
| + temp += fPts[cur]; | 
| + | 
| + // For very shallow angles all the corner points could fuse | 
| + if (duplicate_pt(temp, this->point(newIdx0))) { | 
| + newIdx1 = newIdx0; | 
| + } else { | 
| + newIdx1 = this->addPt(temp, -fTargetDepth, false, false); | 
| + } | 
| + | 
| + // The perpendicular point for the next edge. | 
| + temp = fNorms[cur]; | 
| + temp.scale(fTargetDepth); | 
| + temp += fPts[cur]; | 
| + | 
| + // For very shallow angles all the corner points could fuse. | 
| + if (duplicate_pt(temp, this->point(newIdx1))) { | 
| + newIdx2 = newIdx1; | 
| + } else { | 
| + newIdx2 = this->addPt(temp, -fTargetDepth, false, false); | 
| + } | 
| + | 
| + if (0 == cur) { | 
| + // Store the index of the first perpendicular point to finish up | 
| + firstPerpIdx = newIdx0; | 
| + SkASSERT(-1 == lastPerpIdx); | 
| + } else { | 
| + // The triangles for the previous edge | 
| + this->addTri(prev, newIdx0, cur); | 
| + this->addTri(prev, lastPerpIdx, newIdx0); | 
| + } | 
| + | 
| + // The two triangles for the corner | 
| + this->addTri(cur, newIdx0, newIdx1); | 
| + this->addTri(cur, newIdx1, newIdx2); | 
| + | 
| + prev = cur; | 
| + // Track the last perpendicular outset point so we can construct the | 
| + // trailing edge triangles. | 
| + lastPerpIdx = newIdx2; | 
| } | 
| - | 
| - if (0 == cur) { | 
| - // Store the index of the first perpendicular point to finish up | 
| - firstPerpIdx = newIdx0; | 
| - SkASSERT(-1 == lastPerpIdx); | 
| - } else { | 
| - // The triangles for the previous edge | 
| - this->addTri(prev, newIdx0, cur); | 
| - this->addTri(prev, lastPerpIdx, newIdx0); | 
| - } | 
| - | 
| - // The two triangles for the corner | 
| - this->addTri(cur, newIdx0, newIdx1); | 
| - this->addTri(cur, newIdx1, newIdx2); | 
| - | 
| - prev = cur; | 
| - // Track the last perpendicular outset point so we can construct the | 
| - // trailing edge triangles. | 
| - lastPerpIdx = newIdx2; | 
| } | 
| // pick up the final edge rect | 
| - this->addTri(numPts-1, firstPerpIdx, 0); | 
| - this->addTri(numPts-1, lastPerpIdx, firstPerpIdx); | 
| + this->addTri(numPts - 1, firstPerpIdx, 0); | 
| + this->addTri(numPts - 1, lastPerpIdx, firstPerpIdx); | 
| this->validate(); | 
| } | 
| // Something went wrong in the creation of the next ring. Mark the last good | 
| // ring as being at the desired depth and fan it. | 
| -void GrAAConvexTessellator::terminate(const Ring& ring) { | 
| +void GrAAFlatteningConvexTessellator::terminate(const Ring& ring) { | 
| for (int i = 0; i < ring.numPts(); ++i) { | 
| fDepths[ring.index(i)] = fTargetDepth; | 
| } | 
| @@ -482,7 +487,7 @@ void GrAAConvexTessellator::terminate(const Ring& ring) { | 
| } | 
| // return true when processing is complete | 
| -bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing) { | 
| +bool GrAAFlatteningConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing) { | 
| bool done = false; | 
| fCandidateVerts.rewind(); | 
| @@ -592,7 +597,7 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing | 
| // if the originating index is still valid then this point wasn't | 
| // fused (and is thus movable) | 
| newIdx = this->addPt(fCandidateVerts.point(i), depth, | 
| - fCandidateVerts.originatingIdx(i) != -1); | 
| + fCandidateVerts.originatingIdx(i) != -1, false); | 
| } else { | 
| SkASSERT(fCandidateVerts.originatingIdx(i) != -1); | 
| this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.point(i), depth); | 
| @@ -626,20 +631,20 @@ bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing | 
| return done; | 
| } | 
| -void GrAAConvexTessellator::validate() const { | 
| +void GrAAFlatteningConvexTessellator::validate() const { | 
| SkASSERT(fPts.count() == fDepths.count()); | 
| SkASSERT(fPts.count() == fMovable.count()); | 
| SkASSERT(0 == (fIndices.count() % 3)); | 
| } | 
| ////////////////////////////////////////////////////////////////////////////// | 
| -void GrAAConvexTessellator::Ring::init(const GrAAConvexTessellator& tess) { | 
| +void GrAAFlatteningConvexTessellator::Ring::init(const GrAAFlatteningConvexTessellator& tess) { | 
| this->computeNormals(tess); | 
| this->computeBisectors(tess); | 
| SkASSERT(this->isConvex(tess)); | 
| } | 
| -void GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms, | 
| +void GrAAFlatteningConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms, | 
| const SkTDArray<SkVector>& bisectors) { | 
| for (int i = 0; i < fPts.count(); ++i) { | 
| fPts[i].fNorm = norms[i]; | 
| @@ -648,7 +653,7 @@ void GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms, | 
| } | 
| // Compute the outward facing normal at each vertex. | 
| -void GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& tess) { | 
| +void GrAAFlatteningConvexTessellator::Ring::computeNormals(const GrAAFlatteningConvexTessellator& tess) { | 
| for (int cur = 0; cur < fPts.count(); ++cur) { | 
| int next = (cur + 1) % fPts.count(); | 
| @@ -661,7 +666,7 @@ void GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& te | 
| } | 
| } | 
| -void GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& tess) { | 
| +void GrAAFlatteningConvexTessellator::Ring::computeBisectors(const GrAAFlatteningConvexTessellator& tess) { | 
| int prev = fPts.count() - 1; | 
| for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) { | 
| fPts[cur].fBisector = fPts[cur].fNorm + fPts[prev].fNorm; | 
| @@ -683,7 +688,7 @@ void GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& | 
| ////////////////////////////////////////////////////////////////////////////// | 
| #ifdef SK_DEBUG | 
| // Is this ring convex? | 
| -bool GrAAConvexTessellator::Ring::isConvex(const GrAAConvexTessellator& tess) const { | 
| +bool GrAAFlatteningConvexTessellator::Ring::isConvex(const GrAAFlatteningConvexTessellator& tess) const { | 
| if (fPts.count() < 3) { | 
| return false; | 
| } | 
| @@ -739,7 +744,7 @@ static SkScalar capsule_depth(const SkPoint& p0, const SkPoint& p1, | 
| return perpDist; | 
| } | 
| -SkScalar GrAAConvexTessellator::computeRealDepth(const SkPoint& p) const { | 
| +SkScalar GrAAFlatteningConvexTessellator::computeRealDepth(const SkPoint& p) const { | 
| SkScalar minDist = SK_ScalarMax; | 
| int closestSign, sign; | 
| @@ -759,7 +764,7 @@ SkScalar GrAAConvexTessellator::computeRealDepth(const SkPoint& p) const { | 
| } | 
| // Verify that the incrementally computed depths are close to the actual depths. | 
| -void GrAAConvexTessellator::checkAllDepths() const { | 
| +void GrAAFlatteningConvexTessellator::checkAllDepths() const { | 
| for (int cur = 0; cur < this->numPts(); ++cur) { | 
| SkScalar realDepth = this->computeRealDepth(this->point(cur)); | 
| SkScalar computedDepth = this->depth(cur); | 
| @@ -768,8 +773,78 @@ void GrAAConvexTessellator::checkAllDepths() const { | 
| } | 
| #endif | 
| +#define kQuadTolerance 0.2f | 
| +#define kCubicTolerance 0.2f | 
| +#define kConicTolerance 0.5f | 
| + | 
| +void GrAAFlatteningConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, bool isCurve) { | 
| + m.mapPoints(&p, 1); | 
| + if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) { | 
| + return; | 
| + } | 
| + | 
| + SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1); | 
| + if (this->numPts() >= 2 && | 
| + abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) { | 
| + // The old last point is on the line from the second to last to the new point | 
| + this->popLastPt(); | 
| + fNorms.pop(); | 
| + fIsCurve.pop(); | 
| + } | 
| + this->addPt(p, 0.0f, false, isCurve); | 
| + if (this->numPts() > 1) { | 
| + *fNorms.push() = fPts.top() - fPts[fPts.count()-2]; | 
| + SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top()); | 
| + SkASSERT(len > 0.0f); | 
| + SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length())); | 
| + } | 
| +} | 
| + | 
| +void GrAAFlatteningConvexTessellator::quadTo(const SkMatrix& m, SkPoint* pts) { | 
| + int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); | 
| + fPointBuffer.setReserve(maxCount); | 
| + SkPoint* target = fPointBuffer.begin(); | 
| + int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], | 
| + kQuadTolerance, &target, maxCount); | 
| + fPointBuffer.setCount(count); | 
| + for (int i = 0; i < count; i++) { | 
| + lineTo(m, fPointBuffer[i], true); | 
| + } | 
| +} | 
| + | 
| +void GrAAFlatteningConvexTessellator::cubicTo(const SkMatrix& m, SkPoint* pts) { | 
| + int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); | 
| + fPointBuffer.setReserve(maxCount); | 
| + SkPoint* target = fPointBuffer.begin(); | 
| + int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], | 
| + kCubicTolerance, &target, maxCount); | 
| + fPointBuffer.setCount(count); | 
| + for (int i = 0; i < count; i++) { | 
| + lineTo(m, fPointBuffer[i], true); | 
| + } | 
| +} | 
| + | 
| +// include down here to avoid compilation errors caused by "-" overload in SkGeometry.h | 
| 
 
bsalomon
2015/05/27 17:11:07
What's the error?
 
ethannicholas
2015/05/27 19:22:30
In file included from ../../src/gpu/GrAAFlattening
 
 | 
| +#include "SkGeometry.h" | 
| + | 
| +void GrAAFlatteningConvexTessellator::conicTo(const SkMatrix& m, SkPoint* pts, SkScalar w) { | 
| + SkAutoConicToQuads quadder; | 
| + const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); | 
| + SkPoint lastPoint = *(quads++); | 
| + int count = quadder.countQuads(); | 
| + for (int i = 0; i < count; ++i) { | 
| + SkPoint quadPts[3]; | 
| + quadPts[0] = lastPoint; | 
| + quadPts[1] = quads[0]; | 
| + quadPts[2] = i == count - 1 ? pts[2] : quads[1]; | 
| + quadTo(m, quadPts); | 
| + lastPoint = quadPts[2]; | 
| + quads += 2; | 
| + } | 
| +} | 
| + | 
| ////////////////////////////////////////////////////////////////////////////// | 
| -#if GR_AA_CONVEX_TESSELLATOR_VIZ | 
| +#if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ | 
| static const SkScalar kPointRadius = 0.02f; | 
| static const SkScalar kArrowStrokeWidth = 0.0f; | 
| static const SkScalar kArrowLength = 0.2f; | 
| @@ -812,7 +887,7 @@ static void draw_arrow(SkCanvas*canvas, const SkPoint& p, const SkPoint &n, | 
| paint); | 
| } | 
| -void GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const { | 
| +void GrAAFlatteningConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAFlatteningConvexTessellator& tess) const { | 
| 
 
bsalomon
2015/05/27 17:11:07
nit, 100 col wrap
 
ethannicholas
2015/05/27 19:22:30
Done.
 
 | 
| SkPaint paint; | 
| paint.setTextSize(kEdgeTextSize); | 
| @@ -844,7 +919,7 @@ void GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessell | 
| } | 
| } | 
| -void GrAAConvexTessellator::draw(SkCanvas* canvas) const { | 
| +void GrAAFlatteningConvexTessellator::draw(SkCanvas* canvas) const { | 
| for (int i = 0; i < fIndices.count(); i += 3) { | 
| SkASSERT(fIndices[i] < this->numPts()) ; | 
| SkASSERT(fIndices[i+1] < this->numPts()) ; |