Set ambient stroke to full width of blur.

Gives better blur behavior around corners and looks more like an
actual blur. Also removed the color members, as they're mostly
constant.

Bug: skia:7971
Change-Id: I22a5dcb93da1f39040148ca6ddb391844382cc73
Reviewed-on: https://skia-review.googlesource.com/153280
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Jim Van Verth 2018-09-11 11:37:46 -04:00 committed by Skia Commit-Bot
parent b7c955199a
commit fb18639804
6 changed files with 78 additions and 125 deletions

View File

@ -1020,17 +1020,13 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
// set a large inset to force a fill
devSpaceInsetWidth = ambientRRect.width();
}
// the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur,
// which is just 1/umbraRecipAlpha.
SkScalar blurClamp = SkScalarInvert(umbraRecipAlpha);
std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
ambientColor,
viewMatrix,
ambientRRect,
devSpaceAmbientBlur,
devSpaceInsetWidth,
blurClamp);
devSpaceInsetWidth);
SkASSERT(op);
this->addDrawOp(clip, std::move(op));
}

View File

@ -26,7 +26,7 @@ public:
// emit attributes
varyingHandler->emitAttributes(rsgp);
fragBuilder->codeAppend("half4 shadowParams;");
fragBuilder->codeAppend("half3 shadowParams;");
varyingHandler->addPassThroughAttribute(rsgp.inShadowParams(), "shadowParams");
// setup pass through color
@ -45,7 +45,7 @@ public:
fragBuilder->codeAppend("half d = length(shadowParams.xy);");
fragBuilder->codeAppend("half distance = shadowParams.z * (1.0 - d);");
fragBuilder->codeAppend("half factor = 1.0 - clamp(distance, 0.0, shadowParams.w);");
fragBuilder->codeAppend("half factor = 1.0 - clamp(distance, 0.0, 1.0);");
fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
fragBuilder->codeAppendf("%s = half4(factor);",
args.fOutputCoverage);

View File

@ -45,7 +45,7 @@ private:
static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType};
static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
static constexpr Attribute kInShadowParams = {"inShadowParams", kHalf4_GrVertexAttribType};
static constexpr Attribute kInShadowParams = {"inShadowParams", kHalf3_GrVertexAttribType};
GR_DECLARE_GEOMETRY_PROCESSOR_TEST

View File

@ -192,8 +192,7 @@ public:
// An insetWidth > 1/2 rect width or height indicates a simple fill.
ShadowCircularRRectOp(GrColor color, const SkRect& devRect,
float devRadius, bool isCircle, float blurRadius, float insetWidth,
float blurClamp)
float devRadius, bool isCircle, float blurRadius, float insetWidth)
: INHERITED(ClassID()) {
SkRect bounds = devRect;
SkASSERT(insetWidth > 0);
@ -204,10 +203,6 @@ public:
RRectType type = kFill_RRectType;
if (isCircle) {
umbraInset = 0;
} else if (insetWidth > 0 && insetWidth <= outerRadius) {
// If the client has requested a stroke smaller than the outer radius,
// we will assume they want no special umbra inset (this is for ambient shadows).
umbraInset = outerRadius;
} else {
umbraInset = SkTMax(outerRadius, blurRadius);
}
@ -229,7 +224,7 @@ public:
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
fGeoData.emplace_back(Geometry{color, outerRadius, umbraInset, innerRadius,
blurRadius, blurClamp, bounds, type, isCircle});
blurRadius, bounds, type, isCircle});
if (isCircle) {
fVertCount = circle_type_to_vert_count(kStroke_RRectType == type);
fIndexCount = circle_type_to_index_count(kStroke_RRectType == type);
@ -269,7 +264,6 @@ private:
SkScalar fUmbraInset;
SkScalar fInnerRadius;
SkScalar fBlurRadius;
SkScalar fClampValue;
SkRect fDevBounds;
RRectType fType;
bool fIsCircle;
@ -280,7 +274,6 @@ private:
GrColor fColor;
SkPoint fOffset;
SkScalar fDistanceCorrection;
SkScalar fClampValue;
};
void fillInCircleVerts(const Geometry& args, bool isStroked, CircleVertex** verts) const {
@ -290,7 +283,6 @@ private:
SkScalar innerRadius = args.fInnerRadius;
SkScalar blurRadius = args.fBlurRadius;
SkScalar distanceCorrection = outerRadius / blurRadius;
SkScalar clampValue = args.fClampValue;
const SkRect& bounds = args.fDevBounds;
@ -305,56 +297,48 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-octOffset, -1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(octOffset * halfWidth, -halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(octOffset, -1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(halfWidth, -octOffset * halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(1, -octOffset);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(halfWidth, octOffset * halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(1, octOffset);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(octOffset * halfWidth, halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(octOffset, 1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-octOffset * halfWidth, halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-octOffset, 1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-halfWidth, octOffset * halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-1, octOffset);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-halfWidth, -octOffset * halfWidth);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-1, -octOffset);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
if (isStroked) {
@ -369,56 +353,48 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-s * innerRadius, -c * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(s * r, -c * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(s * innerRadius, -c * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(c * r, -s * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(c * innerRadius, -s * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(c * r, s * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(c * innerRadius, s * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(s * r, c * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(s * innerRadius, c * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-s * r, c * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-s * innerRadius, c * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-c * r, s * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-c * innerRadius, s * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = center + SkPoint::Make(-c * r, -s * r);
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(-c * innerRadius, -s * innerRadius);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
} else {
// filled
@ -426,7 +402,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
}
}
@ -477,7 +452,6 @@ private:
SkScalar diagVal = umbraInset / (SK_ScalarSqrt2*(outerRadius - umbraInset) - outerRadius);
SkVector diagVec = SkVector::Make(diagVal, diagVal);
SkScalar distanceCorrection = umbraInset / blurRadius;
SkScalar clampValue = args.fClampValue;
// build corner by corner
for (int i = 0; i < 4; ++i) {
@ -486,7 +460,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkVector::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
// outer points
@ -494,35 +467,30 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkVector::Make(0, -1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = SkPoint::Make(xOuter[i], yMid[i]);
(*verts)->fColor = color;
(*verts)->fOffset = outerVec;
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = SkPoint::Make(xOuter[i], yOuter[i]);
(*verts)->fColor = color;
(*verts)->fOffset = diagVec;
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = SkPoint::Make(xMid[i], yOuter[i]);
(*verts)->fColor = color;
(*verts)->fOffset = outerVec;
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
(*verts)->fPos = SkPoint::Make(xInner[i], yOuter[i]);
(*verts)->fColor = color;
(*verts)->fOffset = SkVector::Make(0, -1);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
}
@ -540,7 +508,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
// TR
@ -548,7 +515,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
// BL
@ -556,7 +522,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
// BR
@ -564,7 +529,6 @@ private:
(*verts)->fColor = color;
(*verts)->fOffset = SkPoint::Make(0, 0);
(*verts)->fDistanceCorrection = distanceCorrection;
(*verts)->fClampValue = clampValue;
(*verts)++;
}
@ -660,8 +624,7 @@ std::unique_ptr<GrDrawOp> Make(GrContext* context,
const SkMatrix& viewMatrix,
const SkRRect& rrect,
SkScalar blurWidth,
SkScalar insetWidth,
SkScalar blurClamp) {
SkScalar insetWidth) {
// Shadow rrect ops only handle simple circular rrects.
SkASSERT(viewMatrix.isSimilarity() && SkRRectPriv::EqualRadii(rrect));
@ -682,8 +645,7 @@ std::unique_ptr<GrDrawOp> Make(GrContext* context,
scaledRadius,
rrect.isOval(),
blurWidth,
scaledInsetWidth,
blurClamp);
scaledInsetWidth);
}
}
@ -706,23 +668,20 @@ GR_DRAW_OP_TEST_DEFINE(ShadowRRectOp) {
viewMatrix.postScale(scale, scale);
SkScalar insetWidth = random->nextSScalar1() * 72.f;
SkScalar blurWidth = random->nextSScalar1() * 72.f;
SkScalar blurClamp = random->nextSScalar1();
bool isCircle = random->nextBool();
// This op doesn't use a full GrPaint, just a color.
GrColor color = paint.getColor();
if (isCircle) {
SkRect circle = GrTest::TestSquare(random);
SkRRect rrect = SkRRect::MakeOval(circle);
return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth,
insetWidth, blurClamp);
return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth, insetWidth);
} else {
SkRRect rrect;
do {
// This may return a rrect with elliptical corners, which we don't support.
rrect = GrTest::TestRRectSimple(random);
} while (!SkRRectPriv::IsSimpleCircular(rrect));
return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth,
insetWidth, blurClamp);
return GrShadowRRectOp::Make(context, color, viewMatrix, rrect, blurWidth, insetWidth);
}
}

View File

@ -24,8 +24,7 @@ std::unique_ptr<GrDrawOp> Make(GrContext*,
const SkMatrix& viewMatrix,
const SkRRect& rrect,
SkScalar blurWidth,
SkScalar insetWidth,
SkScalar blurClamp = 1);
SkScalar insetWidth);
}
#endif

View File

@ -39,6 +39,8 @@ public:
protected:
static constexpr auto kMinHeight = 0.1f;
static constexpr auto kPenumbraColor = SK_ColorTRANSPARENT;
static constexpr auto kUmbraColor = SK_ColorBLACK;
int vertexCount() const { return fPositions.count(); }
int indexCount() const { return fIndices.count(); }
@ -52,8 +54,9 @@ protected:
bool computeConvexShadow(SkScalar inset, SkScalar outset, bool doClip);
void computeClipVectorsAndTestCentroid();
bool clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, SkPoint* clipPoint);
void addEdge(const SkVector& nextPoint, const SkVector& nextNormal, bool lastEdge, bool doClip);
bool addInnerPoint(const SkPoint& pathPoint, int* currUmbraIndex);
void addEdge(const SkVector& nextPoint, const SkVector& nextNormal, SkColor umbraColor,
bool lastEdge, bool doClip);
bool addInnerPoint(const SkPoint& pathPoint, SkColor umbraColor, int* currUmbraIndex);
int getClosestUmbraPoint(const SkPoint& point);
// concave shadow methods
@ -110,9 +113,6 @@ protected:
bool fIsConvex;
bool fValidUmbra;
SkColor fUmbraColor;
SkColor fPenumbraColor;
SkScalar fDirection;
int fPrevUmbraIndex;
int fCurrUmbraIndex;
@ -123,6 +123,10 @@ protected:
SkPoint fPrevPoint;
};
// make external linkage happy
constexpr SkColor SkBaseShadowTessellator::kUmbraColor;
constexpr SkColor SkBaseShadowTessellator::kPenumbraColor;
static bool compute_normal(const SkPoint& p0, const SkPoint& p1, SkScalar dir,
SkVector* newNormal) {
SkVector normal;
@ -244,6 +248,36 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
this->computeClipVectorsAndTestCentroid();
}
// adjust inset distance and umbra color if necessary
auto umbraColor = kUmbraColor;
SkScalar minDistSq = SkPointPriv::DistanceToLineSegmentBetweenSqd(fCentroid,
fPathPolygon[0],
fPathPolygon[1]);
SkRect bounds;
bounds.setBounds(&fPathPolygon[0], fPathPolygon.count());
for (int i = 1; i < fPathPolygon.count(); ++i) {
int j = i + 1;
if (i == fPathPolygon.count() - 1) {
j = 0;
}
SkPoint currPoint = fPathPolygon[i];
SkPoint nextPoint = fPathPolygon[j];
SkScalar distSq = SkPointPriv::DistanceToLineSegmentBetweenSqd(fCentroid, currPoint,
nextPoint);
if (distSq < minDistSq) {
minDistSq = distSq;
}
}
static constexpr auto kTolerance = 1.0e-2f;
if (minDistSq < (inset + kTolerance)*(inset + kTolerance)) {
// if the umbra would collapse, we back off a bit on inner blur and adjust the alpha
auto newInset = SkScalarSqrt(minDistSq) - kTolerance;
auto ratio = 128 * (newInset + inset) / inset;
// they aren't PMColors, but the interpolation algorithm is the same
umbraColor = SkPMLerp(kUmbraColor, kPenumbraColor, (unsigned)ratio);
inset = newInset;
}
// generate inner ring
if (!SkInsetConvexPolygon(&fPathPolygon[0], fPathPolygon.count(), inset,
&fUmbraPolygon)) {
@ -254,7 +288,7 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
// walk around the path polygon, generate outer ring and connect to inner ring
if (fTransparent) {
fPositions.push_back(fCentroid);
fColors.push_back(fUmbraColor);
fColors.push_back(umbraColor);
}
fCurrUmbraIndex = 0;
@ -273,7 +307,7 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
fPrevPoint = fFirstPoint;
fPrevUmbraIndex = -1;
this->addInnerPoint(fFirstPoint, &fPrevUmbraIndex);
this->addInnerPoint(fFirstPoint, umbraColor, &fPrevUmbraIndex);
if (!fTransparent && doClip) {
SkPoint clipPoint;
@ -281,7 +315,7 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
fCentroid, &clipPoint);
if (isOutside) {
fPositions.push_back(clipPoint);
fColors.push_back(fUmbraColor);
fColors.push_back(umbraColor);
}
fPrevUmbraOutside = isOutside;
fFirstUmbraOutside = isOutside;
@ -289,8 +323,8 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
SkPoint newPoint = fFirstPoint + fFirstOutset;
fPositions.push_back(newPoint);
fColors.push_back(fPenumbraColor);
this->addEdge(fPathPolygon[0], fFirstOutset, false, doClip);
fColors.push_back(kPenumbraColor);
this->addEdge(fPathPolygon[0], fFirstOutset, umbraColor, false, doClip);
for (int i = 1; i < polyCount; ++i) {
SkVector normal;
@ -299,7 +333,7 @@ bool SkBaseShadowTessellator::computeConvexShadow(SkScalar inset, SkScalar outse
}
normal *= outset;
this->addArc(normal, outset, true);
this->addEdge(fPathPolygon[i], normal, i == polyCount - 1, doClip);
this->addEdge(fPathPolygon[i], normal, umbraColor, i == polyCount - 1, doClip);
}
SkASSERT(this->indexCount());
@ -355,7 +389,7 @@ void SkBaseShadowTessellator::computeClipVectorsAndTestCentroid() {
}
void SkBaseShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal,
bool lastEdge, bool doClip) {
SkColor umbraColor, bool lastEdge, bool doClip) {
// add next umbra point
int currUmbraIndex;
bool duplicate;
@ -364,7 +398,7 @@ void SkBaseShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector&
currUmbraIndex = fFirstVertexIndex;
fPrevPoint = nextPoint;
} else {
duplicate = this->addInnerPoint(nextPoint, &currUmbraIndex);
duplicate = this->addInnerPoint(nextPoint, umbraColor, &currUmbraIndex);
}
int prevPenumbraIndex = duplicate || (currUmbraIndex == fFirstVertexIndex)
? fPositions.count() - 1
@ -382,7 +416,7 @@ void SkBaseShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector&
if (isOutside) {
if (!lastEdge) {
fPositions.push_back(clipPoint);
fColors.push_back(fUmbraColor);
fColors.push_back(umbraColor);
}
this->appendTriangle(fPrevUmbraIndex, currUmbraIndex, currUmbraIndex + 1);
if (fPrevUmbraOutside) {
@ -402,7 +436,7 @@ void SkBaseShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector&
// add next penumbra point and quad
SkPoint newPoint = nextPoint + nextNormal;
fPositions.push_back(newPoint);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
if (!duplicate) {
this->appendTriangle(fPrevUmbraIndex, prevPenumbraIndex, currUmbraIndex);
@ -445,7 +479,8 @@ bool SkBaseShadowTessellator::clipUmbraPoint(const SkPoint& umbraPoint, const Sk
return false;
}
bool SkBaseShadowTessellator::addInnerPoint(const SkPoint& pathPoint, int* currUmbraIndex) {
bool SkBaseShadowTessellator::addInnerPoint(const SkPoint& pathPoint, SkColor umbraColor,
int* currUmbraIndex) {
SkPoint umbraPoint;
if (!fValidUmbra) {
SkVector v = fCentroid - pathPoint;
@ -466,7 +501,7 @@ bool SkBaseShadowTessellator::addInnerPoint(const SkPoint& pathPoint, int* currU
} else {
*currUmbraIndex = fPositions.count();
fPositions.push_back(umbraPoint);
fColors.push_back(fUmbraColor);
fColors.push_back(umbraColor);
}
return false;
} else {
@ -583,10 +618,10 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
}
fPositions.push_back(penumbraPolygon[currPenumbra]);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
int prevPenumbraIndex = 0;
fPositions.push_back(umbraPolygon[currUmbra]);
fColors.push_back(fUmbraColor);
fColors.push_back(kUmbraColor);
fPrevUmbraIndex = 1;
indexMap[currUmbra] = 1;
@ -598,11 +633,11 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
if ((*umbraIndices)[nextUmbra] == (*penumbraIndices)[nextPenumbra]) {
// advance both one step
fPositions.push_back(penumbraPolygon[nextPenumbra]);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
int currPenumbraIndex = fPositions.count() - 1;
fPositions.push_back(umbraPolygon[nextUmbra]);
fColors.push_back(fUmbraColor);
fColors.push_back(kUmbraColor);
int currUmbraIndex = fPositions.count() - 1;
indexMap[nextUmbra] = currUmbraIndex;
@ -624,7 +659,7 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
(*penumbraIndices)[nextPenumbra] <= maxPenumbraIndex) {
// fill out penumbra arc
fPositions.push_back(penumbraPolygon[nextPenumbra]);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
int currPenumbraIndex = fPositions.count() - 1;
this->appendTriangle(prevPenumbraIndex, currPenumbraIndex, fPrevUmbraIndex);
@ -640,7 +675,7 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
(*umbraIndices)[nextUmbra] <= maxUmbraIndex) {
// fill out umbra arc
fPositions.push_back(umbraPolygon[nextUmbra]);
fColors.push_back(fUmbraColor);
fColors.push_back(kUmbraColor);
int currUmbraIndex = fPositions.count() - 1;
indexMap[nextUmbra] = currUmbraIndex;
@ -655,11 +690,11 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
}
// finish up by advancing both one step
fPositions.push_back(penumbraPolygon[nextPenumbra]);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
int currPenumbraIndex = fPositions.count() - 1;
fPositions.push_back(umbraPolygon[nextUmbra]);
fColors.push_back(fUmbraColor);
fColors.push_back(kUmbraColor);
int currUmbraIndex = fPositions.count() - 1;
indexMap[nextUmbra] = currUmbraIndex;
@ -800,14 +835,14 @@ bool SkBaseShadowTessellator::addArc(const SkVector& nextNormal, SkScalar offset
currNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin;
currNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin;
fPositions.push_back(fPrevPoint + currNormal);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
this->appendTriangle(fPrevUmbraIndex, fPositions.count() - 1, fPositions.count() - 2);
prevNormal = currNormal;
}
if (finishArc && numSteps) {
fPositions.push_back(fPrevPoint + nextNormal);
fColors.push_back(fPenumbraColor);
fColors.push_back(kPenumbraColor);
this->appendTriangle(fPrevUmbraIndex, fPositions.count() - 1, fPositions.count() - 2);
}
fPrevOutset = nextNormal;
@ -846,8 +881,6 @@ public:
private:
bool computePathPolygon(const SkPath& path, const SkMatrix& ctm);
static constexpr auto kInsetFactor = 0.5f;
typedef SkBaseShadowTessellator INHERITED;
};
@ -857,15 +890,10 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
bool transparent)
: INHERITED(zPlaneParams, transparent) {
// Set base colors
SkScalar baseZ = heightFunc(path.getBounds().centerX(), path.getBounds().centerY());
SkScalar umbraAlpha = SkScalarInvert(SkDrawShadowMetrics::AmbientRecipAlpha(baseZ));
auto baseZ = heightFunc(path.getBounds().centerX(), path.getBounds().centerY());
// umbraColor is the interior value, penumbraColor the exterior value.
// umbraAlpha is the factor that is linearly interpolated from outside to inside, and
// then "blurred" by the GrBlurredEdgeFP. It is then multiplied by fAmbientAlpha to get
// the final alpha.
fUmbraColor = SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0);
fPenumbraColor = SkColorSetARGB(0, 0, 0, 0);
SkScalar outset = SkDrawShadowMetrics::AmbientBlurRadius(baseZ);
auto outset = SkDrawShadowMetrics::AmbientBlurRadius(baseZ);
auto inset = outset * SkDrawShadowMetrics::AmbientRecipAlpha(baseZ) - outset;
if (!this->computePathPolygon(path, ctm)) {
return;
@ -885,9 +913,9 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
fIndices.setReserve(12 * path.countPoints());
if (fIsConvex) {
fSucceeded = this->computeConvexShadow(kInsetFactor, outset, false);
fSucceeded = this->computeConvexShadow(inset, outset, false);
} else {
fSucceeded = this->computeConcaveShadow(kInsetFactor, outset);
fSucceeded = this->computeConcaveShadow(inset, outset);
}
}
@ -961,8 +989,6 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
// Set radius and colors
SkScalar occluderHeight = this->heightFunc(pathBounds.centerX(), pathBounds.centerY());
fUmbraColor = SkColorSetARGB(255, 0, 0, 0);
fPenumbraColor = SkColorSetARGB(0, 0, 0, 0);
// Compute the blur radius, scale and translation for the spot shadow.
SkScalar outset;
@ -1056,33 +1082,6 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
fIndices.setReserve(15 * path.countPoints());
if (fIsConvex) {
SkScalar minDistSq = SkPointPriv::DistanceToLineSegmentBetweenSqd(fCentroid,
fPathPolygon[0],
fPathPolygon[1]);
SkRect bounds;
bounds.setBounds(&fPathPolygon[0], fPathPolygon.count());
for (int i = 1; i < fPathPolygon.count(); ++i) {
int j = i + 1;
if (i == fPathPolygon.count() - 1) {
j = 0;
}
SkPoint currPoint = fPathPolygon[i];
SkPoint nextPoint = fPathPolygon[j];
SkScalar distSq = SkPointPriv::DistanceToLineSegmentBetweenSqd(fCentroid, currPoint,
nextPoint);
if (distSq < minDistSq) {
minDistSq = distSq;
}
}
static constexpr auto kTolerance = 1.0e-2f;
if (minDistSq < (inset + kTolerance)*(inset + kTolerance)) {
// if the umbra would collapse, we back off a bit on inner blur and adjust the alpha
SkScalar newInset = SkScalarSqrt(minDistSq) - kTolerance;
SkScalar ratio = 128 * (newInset + inset) / inset;
// they aren't PMColors, but the interpolation algorithm is the same
fUmbraColor = SkPMLerp(fUmbraColor, fPenumbraColor, (unsigned)ratio);
inset = newInset;
}
fSucceeded = this->computeConvexShadow(inset, outset, true);
} else {
fSucceeded = this->computeConcaveShadow(inset, outset);