aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-01-30 13:11:45 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-30 18:44:38 +0000
commitefe3dedbb3493b738abdb56041b093245e4e8711 (patch)
tree5f38ba81ebc59b48e4888a6e5779e6dbc049c5ad
parent08c5ec71303aa58d6f081914f3e868fa5cce9f4c (diff)
Change shadow tessellators to use SkColor and move to util.
BUG=skia:6119 Change-Id: I4c4a8933c663ccc057596318a06c538175b9f16b Reviewed-on: https://skia-review.googlesource.com/7726 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r--gn/gpu.gni2
-rw-r--r--gn/utils.gni2
-rwxr-xr-xinclude/gpu/effects/GrBlurredEdgeFragmentProcessor.h4
-rwxr-xr-xsrc/effects/shadows/SkAmbientShadowMaskFilter.cpp36
-rwxr-xr-xsrc/effects/shadows/SkSpotShadowMaskFilter.cpp37
-rwxr-xr-xsrc/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp9
-rwxr-xr-xsrc/utils/SkShadowTessellator.cpp (renamed from src/gpu/effects/GrShadowTessellator.cpp)62
-rwxr-xr-xsrc/utils/SkShadowTessellator.h (renamed from src/gpu/effects/GrShadowTessellator.h)36
-rwxr-xr-xsrc/utils/SkShadowUtils.cpp128
9 files changed, 193 insertions, 123 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni
index b3ed69481e..001e6c1eeb 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -329,8 +329,6 @@ skia_gpu_sources = [
"$_src/gpu/effects/GrRRectEffect.h",
"$_src/gpu/effects/GrShadowGeoProc.cpp",
"$_src/gpu/effects/GrShadowGeoProc.h",
- "$_src/gpu/effects/GrShadowTessellator.cpp",
- "$_src/gpu/effects/GrShadowTessellator.h",
"$_src/gpu/effects/GrSimpleTextureEffect.cpp",
"$_src/gpu/effects/GrSimpleTextureEffect.h",
"$_src/gpu/effects/GrSingleTextureEffect.cpp",
diff --git a/gn/utils.gni b/gn/utils.gni
index 068881f605..8d3f1c7a17 100644
--- a/gn/utils.gni
+++ b/gn/utils.gni
@@ -69,6 +69,8 @@ skia_utils_sources = [
"$_src/utils/SkRGBAToYUV.h",
"$_src/utils/SkShadowPaintFilterCanvas.cpp",
"$_src/utils/SkShadowPaintFilterCanvas.h",
+ "$_src/utils/SkShadowTessellator.cpp",
+ "$_src/utils/SkShadowTessellator.h",
"$_src/utils/SkShadowUtils.cpp",
"$_src/utils/SkTextBox.cpp",
"$_src/utils/SkTextureCompressor.cpp",
diff --git a/include/gpu/effects/GrBlurredEdgeFragmentProcessor.h b/include/gpu/effects/GrBlurredEdgeFragmentProcessor.h
index 2e52485791..c9dd27679f 100755
--- a/include/gpu/effects/GrBlurredEdgeFragmentProcessor.h
+++ b/include/gpu/effects/GrBlurredEdgeFragmentProcessor.h
@@ -18,11 +18,11 @@
* If the primitive supports an implicit distance to the edge, the radius of the blur is specified
* by r & g values of the color in 14.2 fixed point. For spot shadows, we increase the stroke width
* to set the shadow against the shape. This pad is specified by b, also in 6.2 fixed point.
+ * The a value represents the max final alpha.
*
* When not using implicit distance, then b in the input color represents the input to the
- * blur function.
+ * blur function, and r the max final alpha.
*
- * In either case, the a value represents the max final alpha.
*/
class GrBlurredEdgeFP : public GrFragmentProcessor {
public:
diff --git a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
index 0672020bcf..9db75c5acb 100755
--- a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
+++ b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
@@ -17,8 +17,6 @@
#include "GrStyle.h"
#include "GrTexture.h"
#include "GrTextureProxy.h"
-#include "effects/GrBlurredEdgeFragmentProcessor.h"
-#include "effects/GrShadowTessellator.h"
#include "SkStrokeRec.h"
#endif
@@ -164,41 +162,21 @@ bool SkAmbientShadowMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texPr
return false;
}
-#ifdef SUPPORT_FAST_PATH
// if circle
// TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
// have our own GeometryProc.
if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
SkRRect rrect = SkRRect::MakeOval(path.getBounds());
- return this->directFilterRRectMaskGPU(nullptr, drawContext, std::move(paint), clip,
+ return this->directFilterRRectMaskGPU(nullptr, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
} else if (path.isRect(nullptr)) {
SkRRect rrect = SkRRect::MakeRect(path.getBounds());
- return this->directFilterRRectMaskGPU(nullptr, drawContext, std::move(paint), clip,
+ return this->directFilterRRectMaskGPU(nullptr, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
}
-#endif
-
- SkScalar radius = fOccluderHeight * kHeightFactor * kGeomFactor;
- SkScalar umbraAlpha = SkScalarInvert((1.0f+SkTMax(fOccluderHeight * kHeightFactor, 0.0f)));
- // 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.
- GrColor umbraColor = GrColorPackRGBA(0, 0, umbraAlpha*255.9999f, fAmbientAlpha*255.9999f);
- GrColor penumbraColor = GrColorPackRGBA(0, 0, 0, fAmbientAlpha*255.9999f);
-
- GrAmbientShadowTessellator tess(path, radius, umbraColor, penumbraColor,
- SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag));
- sk_sp<GrFragmentProcessor> edgeFP = GrBlurredEdgeFP::Make(GrBlurredEdgeFP::kGaussian_Mode);
- paint.addColorFragmentProcessor(std::move(edgeFP));
-
- rtContext->drawVertices(clip, std::move(paint), SkMatrix::I(), kTriangles_GrPrimitiveType,
- tess.vertexCount(), tess.positions(), nullptr,
- tess.colors(), tess.indices(), tess.indexCount());
-
- return true;
+ // TODO
+ return false;
}
bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
@@ -209,10 +187,6 @@ bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
const SkStrokeRec& strokeRec,
const SkRRect& rrect,
const SkRRect& devRRect) const {
-#ifndef SUPPORT_FAST_PATH
- return false;
-#endif
-
// It's likely the caller has already done these checks, but we have to be sure.
// TODO: support analytic blurring of general rrect
@@ -246,7 +220,7 @@ bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
if (fAmbientAlpha > 0.0f) {
SkScalar srcSpaceAmbientRadius = fOccluderHeight * kHeightFactor * kGeomFactor;
const float umbraAlpha = (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f));
- const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
+ const SkScalar ambientOffset = srcSpaceAmbientRadius / umbraAlpha;
// For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
// to get our stroke shape.
diff --git a/src/effects/shadows/SkSpotShadowMaskFilter.cpp b/src/effects/shadows/SkSpotShadowMaskFilter.cpp
index 7a1f3117eb..99a03db091 100755
--- a/src/effects/shadows/SkSpotShadowMaskFilter.cpp
+++ b/src/effects/shadows/SkSpotShadowMaskFilter.cpp
@@ -17,8 +17,6 @@
#include "GrStyle.h"
#include "GrTexture.h"
#include "GrTextureProxy.h"
-#include "effects/GrBlurredEdgeFragmentProcessor.h"
-#include "effects/GrShadowTessellator.h"
#include "SkStrokeRec.h"
#endif
@@ -181,45 +179,20 @@ bool SkSpotShadowMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvi
return false;
}
-#ifdef SUPPORT_FAST_PATH
// if circle
// TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
// have our own GeometryProc.
if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
SkRRect rrect = SkRRect::MakeOval(path.getBounds());
- return this->directFilterRRectMaskGPU(nullptr, drawContext, std::move(paint), clip,
+ return this->directFilterRRectMaskGPU(nullptr, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
} else if (path.isRect(nullptr)) {
SkRRect rrect = SkRRect::MakeRect(path.getBounds());
- return this->directFilterRRectMaskGPU(nullptr, drawContext, std::move(paint), clip,
+ return this->directFilterRRectMaskGPU(nullptr, rtContext, std::move(paint), clip,
SkMatrix::I(), strokeRec, rrect, rrect);
}
-#endif
-
- float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f);
-
- SkScalar radius = fLightRadius * zRatio;
-
- // Compute the scale and translation for the spot shadow.
- const SkScalar scale = fLightPos.fZ / (fLightPos.fZ - fOccluderHeight);
-
- SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
- const SkVector spotOffset = SkVector::Make(zRatio*(center.fX - fLightPos.fX),
- zRatio*(center.fY - fLightPos.fY));
-
- GrColor umbraColor = GrColorPackRGBA(0, 0, 255, fSpotAlpha*255.9999f);
- GrColor penumbraColor = GrColorPackRGBA(0, 0, 0, fSpotAlpha*255.9999f);
- GrSpotShadowTessellator tess(path, scale, spotOffset, radius, umbraColor, penumbraColor,
- SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag));
-
- sk_sp<GrFragmentProcessor> edgeFP = GrBlurredEdgeFP::Make(GrBlurredEdgeFP::kGaussian_Mode);
- paint.addColorFragmentProcessor(std::move(edgeFP));
- rtContext->drawVertices(clip, std::move(paint), SkMatrix::I(), kTriangles_GrPrimitiveType,
- tess.vertexCount(), tess.positions(), nullptr,
- tess.colors(), tess.indices(), tess.indexCount());
-
- return true;
+ return false;
}
bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
@@ -230,10 +203,6 @@ bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
const SkStrokeRec& strokeRec,
const SkRRect& rrect,
const SkRRect& devRRect) const {
-#ifndef SUPPORT_FAST_PATH
- return false;
-#endif
-
// It's likely the caller has already done these checks, but we have to be sure.
// TODO: support analytic blurring of general rrect
diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
index 1441a752c8..502b6e5b95 100755
--- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp
@@ -41,8 +41,13 @@ public:
fragBuilder->codeAppend("factor = smoothstep(factor, 0.0, 1.0);");
break;
}
- fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.a);",
- args.fOutputColor);
+ if (!args.fGpImplementsDistanceVector) {
+ fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.g);",
+ args.fOutputColor);
+ } else {
+ fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.a);",
+ args.fOutputColor);
+ }
}
protected:
diff --git a/src/gpu/effects/GrShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp
index a51a66addd..5ad5e4f758 100755
--- a/src/gpu/effects/GrShadowTessellator.cpp
+++ b/src/utils/SkShadowTessellator.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "GrShadowTessellator.h"
+#include "SkShadowTessellator.h"
#include "GrPathUtils.h"
#include "SkGeometry.h"
@@ -39,10 +39,10 @@ static void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScala
*n = SkScalarFloorToInt(steps);
}
-GrAmbientShadowTessellator::GrAmbientShadowTessellator(const SkPath& path,
+SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
SkScalar radius,
- GrColor umbraColor,
- GrColor penumbraColor,
+ SkColor umbraColor,
+ SkColor penumbraColor,
bool transparent)
: fRadius(radius)
, fUmbraColor(umbraColor)
@@ -142,7 +142,7 @@ static const SkScalar kQuadTolerance = 0.2f;
static const SkScalar kCubicTolerance = 0.2f;
static const SkScalar kConicTolerance = 0.5f;
-void GrAmbientShadowTessellator::handleLine(const SkPoint& p) {
+void SkAmbientShadowTessellator::handleLine(const SkPoint& p) {
if (fInitPoints.count() < 2) {
*fInitPoints.push() = p;
return;
@@ -195,7 +195,9 @@ void GrAmbientShadowTessellator::handleLine(const SkPoint& p) {
}
}
-void GrAmbientShadowTessellator::handleQuad(const SkPoint pts[3]) {
+void SkAmbientShadowTessellator::handleQuad(const SkPoint pts[3]) {
+#if SK_SUPPORT_GPU
+ // TODO: Pull PathUtils out of Ganesh?
int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
fPointBuffer.setReserve(maxCount);
SkPoint* target = fPointBuffer.begin();
@@ -205,9 +207,12 @@ void GrAmbientShadowTessellator::handleQuad(const SkPoint pts[3]) {
for (int i = 0; i < count; i++) {
this->handleLine(fPointBuffer[i]);
}
+#endif
}
-void GrAmbientShadowTessellator::handleCubic(SkPoint pts[4]) {
+void SkAmbientShadowTessellator::handleCubic(SkPoint pts[4]) {
+#if SK_SUPPORT_GPU
+ // TODO: Pull PathUtils out of Ganesh?
int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance);
fPointBuffer.setReserve(maxCount);
SkPoint* target = fPointBuffer.begin();
@@ -217,9 +222,10 @@ void GrAmbientShadowTessellator::handleCubic(SkPoint pts[4]) {
for (int i = 0; i < count; i++) {
this->handleLine(fPointBuffer[i]);
}
+#endif
}
-void GrAmbientShadowTessellator::handleConic(SkPoint pts[3], SkScalar w) {
+void SkAmbientShadowTessellator::handleConic(SkPoint pts[3], SkScalar w) {
SkAutoConicToQuads quadder;
const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
SkPoint lastPoint = *(quads++);
@@ -235,7 +241,7 @@ void GrAmbientShadowTessellator::handleConic(SkPoint pts[3], SkScalar w) {
}
}
-void GrAmbientShadowTessellator::addArc(const SkVector& nextNormal) {
+void SkAmbientShadowTessellator::addArc(const SkVector& nextNormal) {
// fill in fan from previous quad
SkScalar rotSin, rotCos;
int numSteps;
@@ -255,7 +261,7 @@ void GrAmbientShadowTessellator::addArc(const SkVector& nextNormal) {
}
}
-void GrAmbientShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
+void SkAmbientShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
const SkVector& nextNormal) {
// close out previous arc
*fPositions.push() = fPositions[fPrevInnerIndex] + nextNormal;
@@ -267,7 +273,7 @@ void GrAmbientShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
this->addEdge(nextPoint, nextNormal);
}
-void GrAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) {
+void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) {
// add next quad
*fPositions.push() = nextPoint;
*fColors.push() = fUmbraColor;
@@ -298,10 +304,10 @@ void GrAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto
///////////////////////////////////////////////////////////////////////////////////////////////////
-GrSpotShadowTessellator::GrSpotShadowTessellator(const SkPath& path,
+SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path,
SkScalar scale, const SkVector& translate,
SkScalar radius,
- GrColor umbraColor, GrColor penumbraColor,
+ SkColor umbraColor, SkColor penumbraColor,
bool /* transparent */)
: fRadius(radius)
, fUmbraColor(umbraColor)
@@ -394,7 +400,7 @@ GrSpotShadowTessellator::GrSpotShadowTessellator(const SkPath& path,
}
}
-void GrSpotShadowTessellator::computeClipBounds(const SkPath& path) {
+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
SkPath::Iter iter(path, true);
@@ -443,7 +449,7 @@ void GrSpotShadowTessellator::computeClipBounds(const SkPath& path) {
fCentroid *= SkScalarInvert(centroidCount);
}
-void GrSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate,
+void SkSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate,
SkPoint* pts, int count) {
// TODO: vectorize
for (int i = 0; i < count; ++i) {
@@ -452,7 +458,7 @@ void GrSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate,
}
}
-void GrSpotShadowTessellator::handleLine(const SkPoint& p) {
+void SkSpotShadowTessellator::handleLine(const SkPoint& p) {
if (fInitPoints.count() < 2) {
*fInitPoints.push() = p;
return;
@@ -503,12 +509,14 @@ void GrSpotShadowTessellator::handleLine(const SkPoint& p) {
}
}
-void GrSpotShadowTessellator::handleLine(SkScalar scale, const SkVector& xlate, SkPoint p) {
+void SkSpotShadowTessellator::handleLine(SkScalar scale, const SkVector& xlate, SkPoint p) {
this->mapPoints(scale, xlate, &p, 1);
this->handleLine(p);
}
-void GrSpotShadowTessellator::handleQuad(const SkPoint pts[3]) {
+void SkSpotShadowTessellator::handleQuad(const SkPoint pts[3]) {
+#if SK_SUPPORT_GPU
+ // TODO: Pull PathUtils out of Ganesh?
int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
fPointBuffer.setReserve(maxCount);
SkPoint* target = fPointBuffer.begin();
@@ -518,14 +526,17 @@ void GrSpotShadowTessellator::handleQuad(const SkPoint pts[3]) {
for (int i = 0; i < count; i++) {
this->handleLine(fPointBuffer[i]);
}
+#endif
}
-void GrSpotShadowTessellator::handleQuad(SkScalar scale, const SkVector& xlate, SkPoint pts[3]) {
+void SkSpotShadowTessellator::handleQuad(SkScalar scale, const SkVector& xlate, SkPoint pts[3]) {
this->mapPoints(scale, xlate, pts, 3);
this->handleQuad(pts);
}
-void GrSpotShadowTessellator::handleCubic(SkScalar scale, const SkVector& xlate, SkPoint pts[4]) {
+void SkSpotShadowTessellator::handleCubic(SkScalar scale, const SkVector& xlate, SkPoint pts[4]) {
+#if SK_SUPPORT_GPU
+ // TODO: Pull PathUtils out of Ganesh?
this->mapPoints(scale, xlate, pts, 4);
int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance);
fPointBuffer.setReserve(maxCount);
@@ -536,9 +547,10 @@ void GrSpotShadowTessellator::handleCubic(SkScalar scale, const SkVector& xlate,
for (int i = 0; i < count; i++) {
this->handleLine(fPointBuffer[i]);
}
+#endif
}
-void GrSpotShadowTessellator::handleConic(SkScalar scale, const SkVector& xlate,
+void SkSpotShadowTessellator::handleConic(SkScalar scale, const SkVector& xlate,
SkPoint pts[3], SkScalar w) {
this->mapPoints(scale, xlate, pts, 3);
SkAutoConicToQuads quadder;
@@ -556,7 +568,7 @@ void GrSpotShadowTessellator::handleConic(SkScalar scale, const SkVector& xlate,
}
}
-void GrSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint, GrColor umbraColor,
+void SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint, SkColor umbraColor,
SkScalar radius) {
SkVector v = fCentroid - pathPoint;
SkScalar distance = v.length();
@@ -574,7 +586,7 @@ void GrSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint, GrColor um
fPrevPoint = pathPoint;
}
-void GrSpotShadowTessellator::addArc(const SkVector& nextNormal) {
+void SkSpotShadowTessellator::addArc(const SkVector& nextNormal) {
// fill in fan from previous quad
SkScalar rotSin, rotCos;
int numSteps;
@@ -594,7 +606,7 @@ void GrSpotShadowTessellator::addArc(const SkVector& nextNormal) {
}
}
-void GrSpotShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
+void SkSpotShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
const SkVector& nextNormal) {
// close out previous arc
SkPoint newPoint = fPrevPoint + nextNormal;
@@ -607,7 +619,7 @@ void GrSpotShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
this->addEdge(nextPoint, nextNormal);
}
-void GrSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) {
+void SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) {
// add next quad
this->addInnerPoint(nextPoint, fUmbraColor, fRadius);
SkPoint newPoint = nextPoint + nextNormal;
diff --git a/src/gpu/effects/GrShadowTessellator.h b/src/utils/SkShadowTessellator.h
index c2acde72f4..ababba74dd 100755
--- a/src/gpu/effects/GrShadowTessellator.h
+++ b/src/utils/SkShadowTessellator.h
@@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
-#ifndef GrShadowTessellator_DEFINED
-#define GrShadowTessellator_DEFINED
+#ifndef SkShadowTessellator_DEFINED
+#define SkShadowTessellator_DEFINED
#include "SkTDArray.h"
#include "SkPoint.h"
-#include "GrColor.h"
+#include "SkColor.h"
class SkMatrix;
class SkPath;
@@ -23,14 +23,14 @@ class SkPath;
* radius, and setting inner and outer colors to umbraColor and penumbraColor, respectively.
* If transparent is true, then the center of the ambient shadow will be filled in.
*/
-class GrAmbientShadowTessellator {
+class SkAmbientShadowTessellator {
public:
- GrAmbientShadowTessellator(const SkPath& path, SkScalar radius, GrColor umbraColor,
- GrColor penumbraColor, bool transparent);
+ SkAmbientShadowTessellator(const SkPath& path, SkScalar radius, SkColor umbraColor,
+ SkColor penumbraColor, bool transparent);
int vertexCount() { return fPositions.count(); }
SkPoint* positions() { return fPositions.begin(); }
- GrColor* colors() { return fColors.begin(); }
+ SkColor* colors() { return fColors.begin(); }
int indexCount() { return fIndices.count(); }
uint16_t* indices() { return fIndices.begin(); }
@@ -48,12 +48,12 @@ private:
void addEdge(const SkVector& nextPoint, const SkVector& nextNormal);
SkScalar fRadius;
- GrColor fUmbraColor;
- GrColor fPenumbraColor;
+ SkColor fUmbraColor;
+ SkColor fPenumbraColor;
bool fTransparent;
SkTDArray<SkPoint> fPositions;
- SkTDArray<GrColor> fColors;
+ SkTDArray<SkColor> fColors;
SkTDArray<uint16_t> fIndices;
int fPrevInnerIndex;
@@ -74,15 +74,15 @@ private:
* transforming by the scale and translation, and outsetting and insetting by a radius.
* The center will be clipped against the original path unless transparent is true.
*/
-class GrSpotShadowTessellator {
+class SkSpotShadowTessellator {
public:
- GrSpotShadowTessellator(const SkPath& path, SkScalar scale, const SkVector& translate,
- SkScalar radius, GrColor umbraColor, GrColor penumbraColor,
+ SkSpotShadowTessellator(const SkPath& path, SkScalar scale, const SkVector& translate,
+ SkScalar radius, SkColor umbraColor, SkColor penumbraColor,
bool transparent);
int vertexCount() { return fPositions.count(); }
SkPoint* positions() { return fPositions.begin(); }
- GrColor* colors() { return fColors.begin(); }
+ SkColor* colors() { return fColors.begin(); }
int indexCount() { return fIndices.count(); }
uint16_t* indices() { return fIndices.begin(); }
@@ -100,17 +100,17 @@ 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, GrColor umbraColor, SkScalar radiusSqd);
+ 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);
SkScalar fRadius;
- GrColor fUmbraColor;
- GrColor fPenumbraColor;
+ SkColor fUmbraColor;
+ SkColor fPenumbraColor;
SkTDArray<SkPoint> fPositions;
- SkTDArray<GrColor> fColors;
+ SkTDArray<SkColor> fColors;
SkTDArray<uint16_t> fIndices;
int fPrevInnerIndex;
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index e93f778072..5c92d66845 100755
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -7,19 +7,129 @@
#include "SkShadowUtils.h"
#include "SkCanvas.h"
-#include "../effects/shadows/SkAmbientShadowMaskFilter.h"
-#include "../effects/shadows/SkSpotShadowMaskFilter.h"
+#include "SkColorFilter.h"
+#include "SkPath.h"
+#include "SkShadowTessellator.h"
+
+/**
+* Gaussian color filter -- produces a Gaussian ramp based on the color's B value,
+* then blends with the color's G value.
+* Final result is black with alpha of Gaussian(B)*G.
+* The assumption is that the original color's alpha is 1.
+*/
+class SK_API SkGaussianColorFilter : public SkColorFilter {
+public:
+ static sk_sp<SkColorFilter> Make() {
+ return sk_sp<SkColorFilter>(new SkGaussianColorFilter);
+ }
+
+ void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
+
+#if SK_SUPPORT_GPU
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
+#endif
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkGaussianColorFilter)
+
+protected:
+ void flatten(SkWriteBuffer&) const override {}
+
+private:
+ SkGaussianColorFilter() : INHERITED() {}
+
+ typedef SkColorFilter INHERITED;
+};
+
+void SkGaussianColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
+ for (int i = 0; i < count; ++i) {
+ SkPMColor c = src[i];
+
+ SkScalar factor = SK_Scalar1 - SkGetPackedB32(c) / 255.f;
+ factor = SkScalarExp(-factor * factor * 4) - 0.018f;
+
+ dst[i] = SkPackARGB32(factor*SkGetPackedG32(c), 0, 0, 0);
+ }
+}
+
+sk_sp<SkFlattenable> SkGaussianColorFilter::CreateProc(SkReadBuffer&) {
+ return Make();
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void SkGaussianColorFilter::toString(SkString* str) const {
+ str->append("SkGaussianColorFilter ");
+}
+#endif
+
+#if SK_SUPPORT_GPU
+#include "effects/GrBlurredEdgeFragmentProcessor.h"
+
+sk_sp<GrFragmentProcessor> SkGaussianColorFilter::asFragmentProcessor(GrContext*,
+ SkColorSpace*) const {
+ return GrBlurredEdgeFP::Make(GrBlurredEdgeFP::kGaussian_Mode);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+static const float kHeightFactor = 1.0f / 128.0f;
+static const float kGeomFactor = 64.0f;
// Draw an offset spot shadow and outlining ambient shadow for the given path.
void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar occluderHeight,
const SkPoint3& lightPos, SkScalar lightRadius,
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
uint32_t flags) {
- SkPaint newPaint;
- newPaint.setColor(color);
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderHeight, ambientAlpha, flags));
- canvas->drawPath(path, newPaint);
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderHeight, lightPos, lightRadius,
- spotAlpha, flags));
- canvas->drawPath(path, newPaint);
+
+ SkPath xformedPath;
+ // TODO: handle transforming the path as part of the tessellator
+ path.transform(canvas->getTotalMatrix(), &xformedPath);
+ canvas->save();
+ canvas->resetMatrix();
+
+ if (ambientAlpha > 0) {
+ SkScalar radius = occluderHeight * kHeightFactor * kGeomFactor;
+ SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(occluderHeight*kHeightFactor, 0.0f)));
+ // 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.
+ SkColor umbraColor = SkColorSetARGB(255, 0, ambientAlpha*255.9999f, umbraAlpha*255.9999f);
+ SkColor penumbraColor = SkColorSetARGB(255, 0, ambientAlpha*255.9999f, 0);
+
+ SkAmbientShadowTessellator tess(xformedPath, radius, umbraColor, penumbraColor,
+ SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag));
+
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setColorFilter(SkGaussianColorFilter::Make());
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, tess.vertexCount(), tess.positions(),
+ nullptr, tess.colors(), tess.indices(), tess.indexCount(), paint);
+ }
+
+ if (spotAlpha > 0) {
+ float zRatio = SkTPin(occluderHeight / (lightPos.fZ - occluderHeight), 0.0f, 0.95f);
+ SkScalar radius = lightRadius * zRatio;
+
+ // Compute the scale and translation for the spot shadow.
+ const SkScalar scale = lightPos.fZ / (lightPos.fZ - occluderHeight);
+
+ SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
+ const SkVector spotOffset = SkVector::Make(zRatio*(center.fX - lightPos.fX),
+ zRatio*(center.fY - lightPos.fY));
+
+ SkColor umbraColor = SkColorSetARGB(255, 0, spotAlpha*255.9999f, 255);
+ SkColor penumbraColor = SkColorSetARGB(255, 0, spotAlpha*255.9999f, 0);
+ SkSpotShadowTessellator tess(xformedPath, scale, spotOffset, radius,
+ umbraColor, penumbraColor,
+ SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag));
+
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setColorFilter(SkGaussianColorFilter::Make());
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, tess.vertexCount(), tess.positions(),
+ nullptr, tess.colors(), tess.indices(), tess.indexCount(), paint);
+ }
+
+ canvas->restore();
}