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:
parent
b7c955199a
commit
fb18639804
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user