From aa2bd8f726d98edafd28c8553e99cbae33c431dd Mon Sep 17 00:00:00 2001 From: Hal Canary Date: Thu, 2 Feb 2017 19:47:57 +0000 Subject: [PATCH] Revert "Spot shadow cleanup and optimization" This reverts commit 47784c18adc20d1bfefebd00c3ee98c669d79b4d. Reason for revert: MSAN, ASAN Original change's description: > Spot shadow cleanup and optimization > > Fixes clip polygon and centroid calculation. > Clips interior umbra region against original path. > > BUG=skia:6119 > > Change-Id: I37a740ae004c38b75405e05158d92cf9fd954eda > Reviewed-on: https://skia-review.googlesource.com/7823 > Commit-Queue: Brian Salomon > Reviewed-by: Brian Salomon > TBR=jvanverth@google.com,bsalomon@google.com,robertphillips@google.com,reviews@skia.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia:6119 Change-Id: I7a4d9fa3af0d30feac999229f2e94aae2bdafc9c Reviewed-on: https://skia-review.googlesource.com/7947 Reviewed-by: Hal Canary Commit-Queue: Hal Canary --- src/utils/SkShadowTessellator.cpp | 375 ++++++------------------------ 1 file changed, 75 insertions(+), 300 deletions(-) diff --git a/src/utils/SkShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp index a46eb40483..530cdcd50a 100755 --- a/src/utils/SkShadowTessellator.cpp +++ b/src/utils/SkShadowTessellator.cpp @@ -6,7 +6,6 @@ */ #include "SkShadowTessellator.h" -#include "SkColorPriv.h" #include "SkGeometry.h" #include "SkPath.h" @@ -60,7 +59,7 @@ private: SkTDArray fColors; SkTDArray fIndices; - int fPrevUmbraIndex; + int fPrevInnerIndex; SkVector fPrevNormal; int fFirstVertex; SkVector fFirstNormal; @@ -111,7 +110,7 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, , fUmbraColor(umbraColor) , fPenumbraColor(penumbraColor) , fTransparent(transparent) - , fPrevUmbraIndex(-1) { + , fPrevInnerIndex(-1) { // Outer ring: 3*numPts // Middle ring: numPts @@ -155,14 +154,14 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, } SkVector normal; - if (compute_normal(fPositions[fPrevUmbraIndex], fPositions[fFirstVertex], fRadius, fDirection, + if (compute_normal(fPositions[fPrevInnerIndex], fPositions[fFirstVertex], fRadius, fDirection, &normal)) { this->addArc(normal); // close out previous arc - *fPositions.push() = fPositions[fPrevUmbraIndex] + normal; + *fPositions.push() = fPositions[fPrevInnerIndex] + normal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; @@ -170,7 +169,7 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, *fPositions.push() = fPositions[fFirstVertex] + normal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fFirstVertex; @@ -184,13 +183,13 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, fPositions[0] *= SkScalarFastInvert(fCentroidCount); *fIndices.push() = 0; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fFirstVertex; } // final fan if (fPositions.count() >= 3) { - fPrevUmbraIndex = fFirstVertex; + fPrevInnerIndex = fFirstVertex; fPrevNormal = normal; this->addArc(fFirstNormal); @@ -235,7 +234,7 @@ void SkAmbientShadowTessellator::handleLine(const SkPoint& p) { fFirstVertex = fPositions.count(); fPrevNormal = fFirstNormal; - fPrevUmbraIndex = fFirstVertex; + fPrevInnerIndex = fFirstVertex; *fPositions.push() = fInitPoints[0]; *fColors.push() = fUmbraColor; @@ -252,7 +251,7 @@ void SkAmbientShadowTessellator::handleLine(const SkPoint& p) { } SkVector normal; - if (compute_normal(fPositions[fPrevUmbraIndex], p, fRadius, fDirection, &normal)) { + if (compute_normal(fPositions[fPrevInnerIndex], p, fRadius, fDirection, &normal)) { this->addArc(normal); this->finishArcAndAddEdge(p, normal); } @@ -314,9 +313,9 @@ void SkAmbientShadowTessellator::addArc(const SkVector& nextNormal) { SkVector nextNormal; nextNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin; nextNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin; - *fPositions.push() = fPositions[fPrevUmbraIndex] + nextNormal; + *fPositions.push() = fPositions[fPrevInnerIndex] + nextNormal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; @@ -327,9 +326,9 @@ void SkAmbientShadowTessellator::addArc(const SkVector& nextNormal) { void SkAmbientShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { // close out previous arc - *fPositions.push() = fPositions[fPrevUmbraIndex] + nextNormal; + *fPositions.push() = fPositions[fPrevInnerIndex] + nextNormal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; @@ -343,7 +342,7 @@ void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto *fPositions.push() = nextPoint + nextNormal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 3; *fIndices.push() = fPositions.count() - 2; @@ -357,11 +356,11 @@ void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto ++fCentroidCount; *fIndices.push() = 0; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; } - fPrevUmbraIndex = fPositions.count() - 2; + fPrevInnerIndex = fPositions.count() - 2; fPrevNormal = nextNormal; } @@ -390,9 +389,6 @@ public: private: void computeClipBounds(const SkPath& path); - void checkUmbraAndTransformCentroid(SkScalar scale, const SkVector& xlate, - bool useDistanceToPoint); - bool clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, SkPoint* clipPoint); void handleLine(const SkPoint& p); void handleLine(SkScalar scale, const SkVector& xlate, SkPoint p); @@ -405,7 +401,7 @@ private: void handleConic(SkScalar scale, const SkVector& xlate, SkPoint pts[3], SkScalar w); void mapPoints(SkScalar scale, const SkVector& xlate, SkPoint* pts, int count); - void addInnerPoint(const SkPoint& pathPoint); + void addInnerPoint(const SkPoint& pathPoint, SkColor umbraColor, SkScalar radiusSqd); void addArc(const SkVector& nextNormal); void finishArcAndAddEdge(const SkVector& nextPoint, const SkVector& nextNormal); void addEdge(const SkVector& nextPoint, const SkVector& nextNormal); @@ -413,14 +409,12 @@ private: SkScalar fRadius; SkColor fUmbraColor; SkColor fPenumbraColor; - bool fTransparent; - bool fValidUmbra; SkTDArray fPositions; SkTDArray fColors; SkTDArray fIndices; - int fPrevUmbraIndex; + int fPrevInnerIndex; SkPoint fPrevPoint; SkVector fPrevNormal; int fFirstVertex; @@ -430,10 +424,6 @@ private: SkPoint fCentroid; SkTDArray fClipPolygon; - SkTDArray fClipVectors; - int fCurrPolyPoint; - bool fPrevUmbraOutside; - bool fFirstUmbraOutside; // first three points SkTDArray fInitPoints; @@ -441,55 +431,42 @@ private: SkTDArray fPointBuffer; }; - - SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, SkScalar scale, const SkVector& translate, SkScalar radius, SkColor umbraColor, SkColor penumbraColor, - bool transparent) + bool /* transparent */) : fRadius(radius) , fUmbraColor(umbraColor) , fPenumbraColor(penumbraColor) - , fTransparent(transparent) - , fPrevUmbraIndex(-1) { + , fPrevInnerIndex(-1) { // TODO: calculate these better - // Penumbra ring: 3*numPts - // Umbra ring: numPts + // Outer ring: 3*numPts // Inner ring: numPts - fPositions.setReserve(5 * path.countPoints()); - fColors.setReserve(5 * path.countPoints()); - // Penumbra ring: 12*numPts - // Umbra ring: 3*numPts - fIndices.setReserve(15 * path.countPoints()); + fPositions.setReserve(4 * path.countPoints()); + fColors.setReserve(4 * path.countPoints()); + // Outer ring: 12*numPts + // Inner ring: 0 + fIndices.setReserve(12 * path.countPoints()); fInitPoints.setReserve(3); fClipPolygon.setReserve(path.countPoints()); - // compute rough clip bounds for umbra, plus centroid this->computeClipBounds(path); - if (fClipPolygon.count() < 3) { - return; - } // We are going to apply 'scale' and 'xlate' (in that order) to each computed path point. We // want the effect to be to scale the points relative to the path centroid and then translate // them by the 'translate' param we were passed. SkVector xlate = fCentroid * (1.f - scale) + translate; - - // check to see if we have a valid umbra at all - bool usePointCheck = path.isRRect(nullptr) || path.isRect(nullptr) || path.isOval(nullptr); - this->checkUmbraAndTransformCentroid(scale, translate, usePointCheck); - fPrevUmbraOutside = false; + // Also translate the centroid by the global translate. + fCentroid += translate; // walk around the path, tessellate and generate inner and outer rings SkPath::Iter iter(path, true); SkPoint pts[4]; SkPath::Verb verb; - if (fTransparent) { - *fPositions.push() = fCentroid; - *fColors.push() = fUmbraColor; - } + *fPositions.push() = fCentroid; + *fColors.push() = fUmbraColor; while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { switch (verb) { case SkPath::kLine_Verb: @@ -519,69 +496,44 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, // close out previous arc *fPositions.push() = fPrevPoint + normal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; - // add to center fan - if (fTransparent) { - *fIndices.push() = 0; - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = fFirstVertex; - // or to clip ring - } else { - if (fFirstUmbraOutside) { - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = fFirstVertex; - *fIndices.push() = fFirstVertex + 1; - if (fPrevUmbraOutside) { - // fill out quad - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = fFirstVertex + 1; - *fIndices.push() = fPrevUmbraIndex + 1; - } - } else if (fPrevUmbraOutside) { - // add tri - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = fFirstVertex; - *fIndices.push() = fPrevUmbraIndex + 1; - } - } - // add final edge *fPositions.push() = fFirstPoint + normal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fFirstVertex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; *fIndices.push() = fFirstVertex; + + // add to center fan + *fIndices.push() = 0; + *fIndices.push() = fPrevInnerIndex; + *fIndices.push() = fFirstVertex; } // final fan if (fPositions.count() >= 3) { - fPrevUmbraIndex = fFirstVertex; + fPrevInnerIndex = fFirstVertex; fPrevPoint = fFirstPoint; fPrevNormal = normal; this->addArc(fFirstNormal); *fIndices.push() = fFirstVertex; *fIndices.push() = fPositions.count() - 1; - if (fFirstUmbraOutside) { - *fIndices.push() = fFirstVertex + 2; - } else { - *fIndices.push() = fFirstVertex + 1; - } + *fIndices.push() = fFirstVertex + 1; } } void SkSpotShadowTessellator::computeClipBounds(const SkPath& path) { // walk around the path and compute clip polygon // if original path is transparent, will accumulate sum of points for centroid - // for Bezier curves, we compute additional interior points on curve SkPath::Iter iter(path, true); SkPoint pts[4]; SkPath::Verb verb; @@ -590,14 +542,6 @@ void SkSpotShadowTessellator::computeClipBounds(const SkPath& path) { int centroidCount = 0; fClipPolygon.reset(); - // coefficients to compute cubic Bezier at t = 5/16 - const SkScalar kA = 0.32495117187f; - const SkScalar kB = 0.44311523437f; - const SkScalar kC = 0.20141601562f; - const SkScalar kD = 0.03051757812f; - - SkPoint curvePoint; - SkScalar w; while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { switch (verb) { case SkPath::kMove_Verb: @@ -608,41 +552,23 @@ void SkSpotShadowTessellator::computeClipBounds(const SkPath& path) { *fClipPolygon.push() = pts[1]; break; case SkPath::kQuad_Verb: - // point at t = 1/2 - curvePoint.fX = 0.25f*pts[0].fX + 0.5f*pts[1].fX + 0.25f*pts[2].fX; - curvePoint.fY = 0.25f*pts[0].fY + 0.5f*pts[1].fY + 0.25f*pts[2].fY; - *fClipPolygon.push() = curvePoint; - fCentroid += curvePoint; - *fClipPolygon.push() = pts[2]; + fCentroid += pts[1]; fCentroid += pts[2]; centroidCount += 2; + *fClipPolygon.push() = pts[2]; break; case SkPath::kConic_Verb: - // point at t = 1/2 - w = iter.conicWeight(); - curvePoint.fX = 0.25f*pts[0].fX + w*0.5f*pts[1].fX + 0.25f*pts[2].fX; - curvePoint.fY = 0.25f*pts[0].fY + w*0.5f*pts[1].fY + 0.25f*pts[2].fY; - curvePoint *= SkScalarInvert(0.5f + 0.5f*w); - *fClipPolygon.push() = curvePoint; - fCentroid += curvePoint; - *fClipPolygon.push() = pts[2]; + fCentroid += pts[1]; fCentroid += pts[2]; centroidCount += 2; + *fClipPolygon.push() = pts[2]; break; case SkPath::kCubic_Verb: - // point at t = 5/16 - curvePoint.fX = kA*pts[0].fX + kB*pts[1].fX + kC*pts[2].fX + kD*pts[3].fX; - curvePoint.fY = kA*pts[0].fY + kB*pts[1].fY + kC*pts[2].fY + kD*pts[3].fY; - *fClipPolygon.push() = curvePoint; - fCentroid += curvePoint; - // point at t = 11/16 - curvePoint.fX = kD*pts[0].fX + kC*pts[1].fX + kB*pts[2].fX + kA*pts[3].fX; - curvePoint.fY = kD*pts[0].fY + kC*pts[1].fY + kB*pts[2].fY + kA*pts[3].fY; - *fClipPolygon.push() = curvePoint; - fCentroid += curvePoint; - *fClipPolygon.push() = pts[3]; + fCentroid += pts[1]; + fCentroid += pts[2]; fCentroid += pts[3]; centroidCount += 3; + *fClipPolygon.push() = pts[3]; break; case SkPath::kClose_Verb: break; @@ -652,113 +578,6 @@ void SkSpotShadowTessellator::computeClipBounds(const SkPath& path) { } fCentroid *= SkScalarInvert(centroidCount); - fCurrPolyPoint = fClipPolygon.count() - 1; -} - -void SkSpotShadowTessellator::checkUmbraAndTransformCentroid(SkScalar scale, - const SkVector& xlate, - bool useDistanceToPoint) { - SkASSERT(fClipPolygon.count() >= 3); - SkPoint transformedCentroid = fCentroid; - transformedCentroid += xlate; - - SkScalar localRadius = fRadius / scale; - localRadius *= localRadius; - - // init umbra check - SkVector w = fCentroid - fClipPolygon[0]; - SkVector v0 = fClipPolygon[1] - fClipPolygon[0]; - *fClipVectors.push() = v0; - bool validUmbra; - SkScalar minDistance; - // check distance against line segment - if (useDistanceToPoint) { - minDistance = w.lengthSqd(); - } else { - SkScalar vSq = v0.dot(v0); - SkScalar wDotV = w.dot(v0); - minDistance = w.dot(w) - wDotV*wDotV/vSq; - } - validUmbra = (minDistance >= localRadius); - - // init centroid check - bool hiddenCentroid = true; - SkVector v1 = transformedCentroid - fClipPolygon[0]; - SkScalar initCross = v0.cross(v1); - - for (int p = 1; p < fClipPolygon.count(); ++p) { - // Determine whether we have a real umbra by insetting clipPolygon by radius/scale - // and see if it extends past centroid. - // TODO: adjust this later for more accurate umbra calcs - w = fCentroid - fClipPolygon[p]; - v0 = fClipPolygon[(p + 1) % fClipPolygon.count()] - fClipPolygon[p]; - *fClipVectors.push() = v0; - // check distance against line segment - SkScalar distance; - if (useDistanceToPoint) { - distance = w.lengthSqd(); - } else { - SkScalar vSq = v0.dot(v0); - SkScalar wDotV = w.dot(v0); - distance = w.dot(w) - wDotV*wDotV/vSq; - } - if (distance < localRadius) { - validUmbra = false; - } - if (distance < minDistance) { - minDistance = distance; - } - // Determine if transformed centroid is inside clipPolygon. - v1 = transformedCentroid - fClipPolygon[p]; - if (initCross*v0.cross(v1) <= 0) { - hiddenCentroid = false; - } - } - SkASSERT(fClipVectors.count() == fClipPolygon.count()); - - if (!validUmbra) { - SkScalar ratio = 256 * SkScalarSqrt(minDistance / localRadius); - // they aren't PMColors, but the interpolation algorithm is the same - fUmbraColor = SkPMLerp(fUmbraColor, fPenumbraColor, (unsigned)ratio); - } - - fTransparent = fTransparent || !hiddenCentroid || !validUmbra; - fValidUmbra = validUmbra; - fCentroid = transformedCentroid; -} - -bool SkSpotShadowTessellator::clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, - SkPoint* clipPoint) { - SkVector segmentVector = centroid - umbraPoint; - - int startPolyPoint = fCurrPolyPoint; - do { - SkVector dp = umbraPoint - fClipPolygon[fCurrPolyPoint]; - SkScalar denom = fClipVectors[fCurrPolyPoint].cross(segmentVector); - SkScalar t_num = dp.cross(segmentVector); - // if line segments are nearly parallel - if (SkScalarNearlyZero(denom)) { - // and collinear - if (SkScalarNearlyZero(t_num)) { - return false; - } - // otherwise are separate, will try the next poly segment - // else if crossing lies within poly segment - } else if (t_num >= 0 && t_num <= denom) { - SkScalar s_num = dp.cross(fClipVectors[fCurrPolyPoint]); - // if umbra point is inside the clip polygon - if (s_num < 0) { - return false; - } else { - segmentVector *= s_num/denom; - *clipPoint = umbraPoint + segmentVector; - return true; - } - } - fCurrPolyPoint = (fCurrPolyPoint + 1) % fClipPolygon.count(); - } while (fCurrPolyPoint != startPolyPoint); - - return false; } void SkSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate, @@ -802,21 +621,9 @@ void SkSpotShadowTessellator::handleLine(const SkPoint& p) { fFirstVertex = fPositions.count(); fPrevNormal = fFirstNormal; fPrevPoint = fFirstPoint; - fPrevUmbraIndex = fFirstVertex; - - this->addInnerPoint(fFirstPoint); - - if (!fTransparent) { - SkPoint clipPoint; - bool isOutside = this->clipUmbraPoint(fPositions[fFirstVertex], fCentroid, &clipPoint); - if (isOutside) { - *fPositions.push() = clipPoint; - *fColors.push() = fUmbraColor; - } - fPrevUmbraOutside = isOutside; - fFirstUmbraOutside = isOutside; - } + fPrevInnerIndex = fFirstVertex; + this->addInnerPoint(fFirstPoint, fUmbraColor, fRadius); SkPoint newPoint = fFirstPoint + fFirstNormal; *fPositions.push() = newPoint; *fColors.push() = fPenumbraColor; @@ -892,21 +699,21 @@ void SkSpotShadowTessellator::handleConic(SkScalar scale, const SkVector& xlate, } } -void SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint) { +void SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint, SkColor umbraColor, + SkScalar radius) { SkVector v = fCentroid - pathPoint; SkScalar distance = v.length(); - SkScalar t; - if (fValidUmbra) { - SkASSERT(distance >= fRadius); - t = fRadius / distance; + if (distance < radius) { + *fPositions.push() = fCentroid; + *fColors.push() = umbraColor; // fix this + // TODO: deal with fanning from centroid } else { - t = 0.95f; + SkScalar t = radius / distance; + v *= t; + SkPoint innerPoint = pathPoint + v; + *fPositions.push() = innerPoint; + *fColors.push() = umbraColor; } - v *= t; - SkPoint umbraPoint = pathPoint + v; - *fPositions.push() = umbraPoint; - *fColors.push() = fUmbraColor; - fPrevPoint = pathPoint; } @@ -922,7 +729,7 @@ void SkSpotShadowTessellator::addArc(const SkVector& nextNormal) { nextNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin; *fPositions.push() = fPrevPoint + nextNormal; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; @@ -936,7 +743,7 @@ void SkSpotShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, SkPoint newPoint = fPrevPoint + nextNormal; *fPositions.push() = newPoint; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; + *fIndices.push() = fPrevInnerIndex; *fIndices.push() = fPositions.count() - 2; *fIndices.push() = fPositions.count() - 1; @@ -944,58 +751,26 @@ void SkSpotShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, } void SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { - // add next umbra point - this->addInnerPoint(nextPoint); - int prevPenumbraIndex = fPositions.count() - 2; - int currUmbraIndex = fPositions.count() - 1; - - // add to center fan if transparent or centroid showing - if (fTransparent) { - *fIndices.push() = 0; - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = currUmbraIndex; - // otherwise add to clip ring - } else { - if (!fTransparent) { - SkPoint clipPoint; - bool isOutside = clipUmbraPoint(fPositions[currUmbraIndex], fCentroid, &clipPoint); - if (isOutside) { - *fPositions.push() = clipPoint; - *fColors.push() = fUmbraColor; - - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = currUmbraIndex; - *fIndices.push() = currUmbraIndex + 1; - if (fPrevUmbraOutside) { - // fill out quad - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = currUmbraIndex + 1; - *fIndices.push() = fPrevUmbraIndex + 1; - } - } else if (fPrevUmbraOutside) { - // add tri - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = currUmbraIndex; - *fIndices.push() = fPrevUmbraIndex + 1; - } - fPrevUmbraOutside = isOutside; - } - } - - // add next penumbra point and quad + // add next quad + this->addInnerPoint(nextPoint, fUmbraColor, fRadius); SkPoint newPoint = nextPoint + nextNormal; *fPositions.push() = newPoint; *fColors.push() = fPenumbraColor; - *fIndices.push() = fPrevUmbraIndex; - *fIndices.push() = prevPenumbraIndex; - *fIndices.push() = currUmbraIndex; + *fIndices.push() = fPrevInnerIndex; + *fIndices.push() = fPositions.count() - 3; + *fIndices.push() = fPositions.count() - 2; - *fIndices.push() = prevPenumbraIndex; + *fIndices.push() = fPositions.count() - 3; *fIndices.push() = fPositions.count() - 1; - *fIndices.push() = currUmbraIndex; + *fIndices.push() = fPositions.count() - 2; - fPrevUmbraIndex = currUmbraIndex; + // add to center fan + *fIndices.push() = 0; + *fIndices.push() = fPrevInnerIndex; + *fIndices.push() = fPositions.count() - 2; + + fPrevInnerIndex = fPositions.count() - 2; fPrevNormal = nextNormal; }