Revert "Spot shadow cleanup and optimization"

This reverts commit 47784c18ad.

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 <bsalomon@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> 

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 <halcanary@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
This commit is contained in:
Hal Canary 2017-02-02 19:47:57 +00:00 committed by Skia Commit-Bot
parent 6bf4891c1e
commit aa2bd8f726

View File

@ -6,7 +6,6 @@
*/
#include "SkShadowTessellator.h"
#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkPath.h"
@ -60,7 +59,7 @@ private:
SkTDArray<SkColor> fColors;
SkTDArray<uint16_t> 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<SkPoint> fPositions;
SkTDArray<SkColor> fColors;
SkTDArray<uint16_t> fIndices;
int fPrevUmbraIndex;
int fPrevInnerIndex;
SkPoint fPrevPoint;
SkVector fPrevNormal;
int fFirstVertex;
@ -430,10 +424,6 @@ private:
SkPoint fCentroid;
SkTDArray<SkPoint> fClipPolygon;
SkTDArray<SkVector> fClipVectors;
int fCurrPolyPoint;
bool fPrevUmbraOutside;
bool fFirstUmbraOutside;
// first three points
SkTDArray<SkPoint> fInitPoints;
@ -441,55 +431,42 @@ private:
SkTDArray<SkPoint> 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;
}