diff options
-rw-r--r-- | include/utils/SkShadowUtils.h | 27 | ||||
-rw-r--r-- | samplecode/SampleAndroidShadows.cpp | 9 | ||||
-rw-r--r-- | src/utils/SkShadowTessellator.cpp | 88 | ||||
-rw-r--r-- | src/utils/SkShadowTessellator.h | 13 | ||||
-rw-r--r-- | src/utils/SkShadowUtils.cpp | 108 | ||||
-rw-r--r-- | tests/ShadowUtilsTest.cpp | 22 |
6 files changed, 185 insertions, 82 deletions
diff --git a/include/utils/SkShadowUtils.h b/include/utils/SkShadowUtils.h index 3339812c34..01514a46ff 100644 --- a/include/utils/SkShadowUtils.h +++ b/include/utils/SkShadowUtils.h @@ -11,6 +11,7 @@ #include "SkColor.h" #include "SkScalar.h" #include "../private/SkShadowFlags.h" +#include <functional> class SkCanvas; class SkPath; @@ -25,7 +26,7 @@ public: * @param canvas The canvas on which to draw the shadows. * @param path The occluder used to generate the shadows. * @param occluderHeight The vertical offset of the occluder from the canvas. This is - * indepdendent of the canvas's current matrix. + * independent of the canvas's current matrix. * @param lightPos The 3D position of the light relative to the canvas plane. This is * independent of the canvas's current matrix. * @param lightRadius The radius of the disc light. @@ -41,6 +42,30 @@ public: SkScalar spotAlpha, SkColor color, uint32_t flags = SkShadowFlags::kNone_ShadowFlag, SkResourceCache* cache = nullptr); + + /** + * Draw an offset spot shadow and outlining ambient shadow for the given path using a disc + * light. Takes a function to vary the z value based on the transformed x and y position. + * This shadow will not be cached, as the assumption is that this will be used for animation. + * + * @param canvas The canvas on which to draw the shadows. + * @param path The occluder used to generate the shadows. + * @param heightFunc A function which returns the vertical offset of the occluder from the + * canvas based on local x and y values (the current matrix is not applied). + * @param lightPos The 3D position of the light relative to the canvas plane. This is + * independent of the canvas's current matrix. + * @param lightRadius The radius of the disc light. + * @param ambientAlpha The maximum alpha of the ambient shadow. + * @param spotAlpha The maxium alpha of the spot shadow. + * @param color The shadow color. + * @param flags Options controlling opaque occluder optimizations and shadow appearance. See + * SkShadowFlags. + */ + static void DrawUncachedShadow(SkCanvas* canvas, const SkPath& path, + std::function<SkScalar(SkScalar, SkScalar)> heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color, + uint32_t flags = SkShadowFlags::kNone_ShadowFlag); }; #endif diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp index 271004ed10..bb56b7ed17 100644 --- a/samplecode/SampleAndroidShadows.cpp +++ b/samplecode/SampleAndroidShadows.cpp @@ -421,8 +421,15 @@ protected: if (!fShowSpot) { spotAlpha = 0; } - SkShadowUtils::DrawShadow(canvas, path, zValue, lightPos, lightWidth, + + SkShadowUtils::DrawShadow(canvas, path, + zValue, + lightPos, lightWidth, ambientAlpha, spotAlpha, SK_ColorBLACK); + //SkShadowUtils::DrawUncachedShadow(canvas, path, + // [zValue](SkScalar, SkScalar) { return zValue; }, + // lightPos, lightWidth, + // ambientAlpha, spotAlpha, SK_ColorBLACK); } #else if (fShowAmbient) { diff --git a/src/utils/SkShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp index ef8ce3212f..ce161ca8de 100644 --- a/src/utils/SkShadowTessellator.cpp +++ b/src/utils/SkShadowTessellator.cpp @@ -22,8 +22,7 @@ */ class SkBaseShadowTessellator { public: - SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor, SkColor penumbraColor, - bool transparent); + SkBaseShadowTessellator(SkShadowTessellator::HeightFunc, bool transparent); virtual ~SkBaseShadowTessellator() {} sk_sp<SkVertices> releaseVertices() { @@ -53,6 +52,8 @@ protected: void finishArcAndAddEdge(const SkVector& nextPoint, const SkVector& nextNormal); virtual void addEdge(const SkVector& nextPoint, const SkVector& nextNormal) = 0; + SkShadowTessellator::HeightFunc fHeightFunc; + // first three points SkTDArray<SkPoint> fInitPoints; // temporary buffer @@ -108,14 +109,12 @@ static void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScala *n = SkScalarFloorToInt(steps); } -SkBaseShadowTessellator::SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor, - SkColor penumbraColor, bool transparent) - : fFirstVertex(-1) +SkBaseShadowTessellator::SkBaseShadowTessellator(SkShadowTessellator::HeightFunc heightFunc, + bool transparent) + : fHeightFunc(heightFunc) + , fFirstVertex(-1) , fSucceeded(false) , fTransparent(transparent) - , fUmbraColor(umbraColor) - , fPenumbraColor(penumbraColor) - , fRadius(radius) , fDirection(1) , fPrevUmbraIndex(-1) { fInitPoints.setReserve(3); @@ -235,8 +234,8 @@ void SkBaseShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, class SkAmbientShadowTessellator : public SkBaseShadowTessellator { public: SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, - SkScalar radius, SkColor umbraColor, - SkColor penumbraColor, bool transparent); + SkShadowTessellator::HeightFunc heightFunc, + SkScalar ambientAlpha, bool transparent); private: void handleLine(const SkPoint& p) override; @@ -247,13 +246,27 @@ private: typedef SkBaseShadowTessellator INHERITED; }; +static const float kHeightFactor = 1.0f / 128.0f; +static const float kGeomFactor = 64.0f; + SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, - SkScalar radius, - SkColor umbraColor, - SkColor penumbraColor, + SkShadowTessellator::HeightFunc heightFunc, + SkScalar ambientAlpha, bool transparent) - : INHERITED(radius, umbraColor, penumbraColor, transparent) { + : INHERITED(heightFunc, transparent) { + // Set radius and colors + // TODO: vary colors and radius based on heightFunc + SkScalar occluderHeight = heightFunc(0, 0); + fRadius = 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. + fUmbraColor = SkColorSetARGB(255, 0, ambientAlpha * 255.9999f, umbraAlpha * 255.9999f); + fPenumbraColor = SkColorSetARGB(255, 0, ambientAlpha * 255.9999f, 0); + // Outer ring: 3*numPts // Middle ring: numPts fPositions.setReserve(4 * path.countPoints()); @@ -269,7 +282,7 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, SkPath::Verb verb; if (fTransparent) { *fPositions.push() = SkPoint::Make(0, 0); - *fColors.push() = umbraColor; + *fColors.push() = fUmbraColor; fCentroidCount = 0; } while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { @@ -435,9 +448,9 @@ void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto class SkSpotShadowTessellator : public SkBaseShadowTessellator { public: SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, - SkScalar scale, const SkVector& translate, - SkScalar radius, SkColor umbraColor, SkColor penumbraColor, - bool transparent); + SkShadowTessellator::HeightFunc heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar spotAlpha, bool transparent); private: void computeClipAndPathPolygons(const SkPath& path, const SkMatrix& ctm, @@ -470,14 +483,31 @@ private: }; SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, - SkScalar scale, const SkVector& translate, - SkScalar radius, SkColor umbraColor, - SkColor penumbraColor, bool transparent) - : INHERITED(radius, umbraColor, penumbraColor, transparent) + SkShadowTessellator::HeightFunc heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar spotAlpha, bool transparent) + : INHERITED(heightFunc, transparent) , fCurrClipPoint(0) , fPrevUmbraOutside(false) , fFirstUmbraOutside(false) , fValidUmbra(true) { + + // Set radius and colors + // TODO: vary colors and radius based on heightFunc + SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY()); + SkScalar occluderHeight = heightFunc(center.fX, center.fY); + float zRatio = SkTPin(occluderHeight / (lightPos.fZ - occluderHeight), 0.0f, 0.95f); + SkScalar radius = lightRadius * zRatio; + fRadius = radius; + fUmbraColor = SkColorSetARGB(255, 0, spotAlpha * 255.9999f, 255); + fPenumbraColor = SkColorSetARGB(255, 0, spotAlpha * 255.9999f, 0); + + // Compute the scale and translation for the spot shadow. + SkScalar scale = lightPos.fZ / (lightPos.fZ - occluderHeight); + ctm.mapPoints(¢er, 1); + SkVector translate = SkVector::Make(zRatio * (center.fX - lightPos.fX), + zRatio * (center.fY - lightPos.fY)); + // TODO: calculate these reserves better // Penumbra ring: 3*numPts // Umbra ring: numPts @@ -993,17 +1023,17 @@ void SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& /////////////////////////////////////////////////////////////////////////////////////////////////// sk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm, - SkScalar radius, SkColor umbra, SkColor penumbra, + HeightFunc heightFunc, SkScalar ambientAlpha, bool transparent) { - SkAmbientShadowTessellator ambientTess(path, ctm, radius, umbra, penumbra, transparent); + SkAmbientShadowTessellator ambientTess(path, ctm, heightFunc, ambientAlpha, transparent); return ambientTess.releaseVertices(); } sk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm, - SkScalar scale, const SkVector& translate, - SkScalar radius, SkColor umbraColor, - SkColor penumbraColor, bool transparent) { - SkSpotShadowTessellator spotTess(path, ctm, scale, translate, radius, umbraColor, - penumbraColor, transparent); + HeightFunc heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar spotAlpha, bool transparent) { + SkSpotShadowTessellator spotTess(path, ctm, heightFunc, lightPos, lightRadius, + spotAlpha, transparent); return spotTess.releaseVertices(); } diff --git a/src/utils/SkShadowTessellator.h b/src/utils/SkShadowTessellator.h index eb49bbee3f..f9f4a144c9 100644 --- a/src/utils/SkShadowTessellator.h +++ b/src/utils/SkShadowTessellator.h @@ -17,22 +17,25 @@ class SkPath; class SkVertices; namespace SkShadowTessellator { + +typedef std::function<SkScalar(SkScalar, SkScalar)> HeightFunc; + /** * This function generates an ambient shadow mesh for a path by walking the path, outsetting by * the 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. */ -sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm, SkScalar radius, - SkColor umbraColor, SkColor penumbraColor, bool transparent); +sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm, + HeightFunc heightFunc, SkScalar ambientAlpha, bool transparent); /** * This function generates a spot shadow mesh for a path by walking the transformed path, * further 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. */ -sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, SkScalar scale, - const SkVector& translate, SkScalar radius, SkColor umbraColor, - SkColor penumbraColor, bool transparent); +sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, HeightFunc heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar spotAlpha, bool transparent); } #endif diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp index 402dca5c92..2e560b454e 100644 --- a/src/utils/SkShadowUtils.cpp +++ b/src/utils/SkShadowUtils.cpp @@ -92,14 +92,13 @@ uint64_t resource_cache_shared_id() { /** Factory for an ambient shadow mesh with particular shadow properties. */ struct AmbientVerticesFactory { - SkScalar fRadius = SK_ScalarNaN; // NaN so that isCompatible will always fail until init'ed. - SkColor fUmbraColor; - SkColor fPenumbraColor; + SkScalar fOccluderHeight = SK_ScalarNaN; // NaN so that isCompatible will fail until init'ed. + SkScalar fAmbientAlpha; bool fTransparent; bool isCompatible(const AmbientVerticesFactory& that, SkVector* translate) const { - if (fRadius != that.fRadius || fUmbraColor != that.fUmbraColor || - fPenumbraColor != that.fPenumbraColor || fTransparent != that.fTransparent) { + if (fOccluderHeight != that.fOccluderHeight || fAmbientAlpha != that.fAmbientAlpha || + fTransparent != that.fTransparent) { return false; } translate->set(0, 0); @@ -107,8 +106,10 @@ struct AmbientVerticesFactory { } sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const { - return SkShadowTessellator::MakeAmbient(path, ctm, fRadius, fUmbraColor, fPenumbraColor, - fTransparent); + SkScalar z = fOccluderHeight; + return SkShadowTessellator::MakeAmbient(path, ctm, + [z](SkScalar, SkScalar) { return z; }, + fAmbientAlpha, fTransparent); } }; @@ -123,17 +124,17 @@ struct SpotVerticesFactory { kOpaqueCoversUmbra }; - SkScalar fRadius = SK_ScalarNaN; // NaN so that isCompatible will always fail until init'ed. - SkColor fUmbraColor; - SkColor fPenumbraColor; - SkScalar fScale; SkVector fOffset; + SkScalar fOccluderHeight = SK_ScalarNaN; // NaN so that isCompatible will fail until init'ed. + SkPoint3 fDevLightPos; + SkScalar fLightRadius; + SkScalar fSpotAlpha; OccluderType fOccluderType; bool isCompatible(const SpotVerticesFactory& that, SkVector* translate) const { - if (fRadius != that.fRadius || fUmbraColor != that.fUmbraColor || - fPenumbraColor != that.fPenumbraColor || fOccluderType != that.fOccluderType || - fScale != that.fScale) { + if (fOccluderHeight != that.fOccluderHeight || fDevLightPos.fZ != that.fDevLightPos.fZ || + fLightRadius != that.fLightRadius || fSpotAlpha != that.fSpotAlpha || + fOccluderType != that.fOccluderType) { return false; } switch (fOccluderType) { @@ -158,8 +159,11 @@ struct SpotVerticesFactory { sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const { bool transparent = OccluderType::kTransparent == fOccluderType; - return SkShadowTessellator::MakeSpot(path, ctm, fScale, fOffset, fRadius, fUmbraColor, - fPenumbraColor, transparent); + SkScalar z = fOccluderHeight; + return SkShadowTessellator::MakeSpot(path, ctm, + [z](SkScalar, SkScalar) -> SkScalar { return z; }, + fDevLightPos, fLightRadius, + fSpotAlpha, transparent); } }; @@ -450,9 +454,6 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S } } -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& devLightPos, SkScalar lightRadius, @@ -489,15 +490,8 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc if (ambientAlpha > 0) { ambientAlpha = SkTMin(ambientAlpha, 1.f); AmbientVerticesFactory factory; - factory.fRadius = 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. - factory.fUmbraColor = - SkColorSetARGB(255, 0, ambientAlpha * 255.9999f, umbraAlpha * 255.9999f); - factory.fPenumbraColor = SkColorSetARGB(255, 0, ambientAlpha * 255.9999f, 0); + factory.fOccluderHeight = occluderHeight; + factory.fAmbientAlpha = ambientAlpha; factory.fTransparent = transparent; draw_shadow(factory, canvas, shadowedPath, color, cache); @@ -507,17 +501,19 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc spotAlpha = SkTMin(spotAlpha, 1.f); SpotVerticesFactory factory; float zRatio = SkTPin(occluderHeight / (devLightPos.fZ - occluderHeight), 0.0f, 0.95f); - factory.fRadius = lightRadius * zRatio; + SkScalar radius = lightRadius * zRatio; // Compute the scale and translation for the spot shadow. - factory.fScale = devLightPos.fZ / (devLightPos.fZ - occluderHeight); + SkScalar scale = devLightPos.fZ / (devLightPos.fZ - occluderHeight); SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY()); viewMatrix.mapPoints(¢er, 1); factory.fOffset = SkVector::Make(zRatio * (center.fX - devLightPos.fX), zRatio * (center.fY - devLightPos.fY)); - factory.fUmbraColor = SkColorSetARGB(255, 0, spotAlpha * 255.9999f, 255); - factory.fPenumbraColor = SkColorSetARGB(255, 0, spotAlpha * 255.9999f, 0); + factory.fOccluderHeight = occluderHeight; + factory.fDevLightPos = devLightPos; + factory.fLightRadius = lightRadius; + factory.fSpotAlpha = spotAlpha; SkRRect rrect; if (transparent) { @@ -527,13 +523,13 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc if (shadowedPath.isRRect(&rrect)) { SkRRect devRRect; if (rrect.transform(viewMatrix, &devRRect)) { - SkScalar s = 1.f - factory.fScale; + SkScalar s = 1.f - scale; SkScalar w = devRRect.width(); SkScalar h = devRRect.height(); SkScalar hw = w / 2.f; SkScalar hh = h / 2.f; - SkScalar umbraInsetX = s * hw + factory.fRadius; - SkScalar umbraInsetY = s * hh + factory.fRadius; + SkScalar umbraInsetX = s * hw + radius; + SkScalar umbraInsetY = s * hh + radius; // The umbra is inset by radius along the diagonal, so adjust for that. SkScalar d = 1.f / SkScalarSqrt(hw * hw + hh * hh); umbraInsetX *= hw * d; @@ -559,3 +555,45 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc draw_shadow(factory, canvas, shadowedPath, color, cache); } } + +// Draw an offset spot shadow and outlining ambient shadow for the given path, +// without caching and using a function based on local position to compute the height. +void SkShadowUtils::DrawUncachedShadow(SkCanvas* canvas, const SkPath& path, + std::function<SkScalar(SkScalar, SkScalar)> heightFunc, + const SkPoint3& lightPos, SkScalar lightRadius, + SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color, + uint32_t flags) { + SkAutoCanvasRestore acr(canvas, true); + SkMatrix viewMatrix = canvas->getTotalMatrix(); + canvas->resetMatrix(); + + bool transparent = SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag); + + if (ambientAlpha > 0) { + ambientAlpha = SkTMin(ambientAlpha, 1.f); + sk_sp<SkVertices> vertices = SkShadowTessellator::MakeAmbient(path, viewMatrix, + heightFunc, ambientAlpha, + transparent); + SkPaint paint; + // Run the vertex color through a GaussianColorFilter and then modulate the grayscale + // result of that against our 'color' param. + paint.setColorFilter(SkColorFilter::MakeComposeFilter( + SkColorFilter::MakeModeFilter(color, SkBlendMode::kModulate), + SkGaussianColorFilter::Make())); + canvas->drawVertices(vertices, SkBlendMode::kModulate, paint); + } + + if (spotAlpha > 0) { + spotAlpha = SkTMin(spotAlpha, 1.f); + sk_sp<SkVertices> vertices = SkShadowTessellator::MakeSpot(path, viewMatrix, heightFunc, + lightPos, lightRadius, + spotAlpha, transparent); + SkPaint paint; + // Run the vertex color through a GaussianColorFilter and then modulate the grayscale + // result of that against our 'color' param. + paint.setColorFilter(SkColorFilter::MakeComposeFilter( + SkColorFilter::MakeModeFilter(color, SkBlendMode::kModulate), + SkGaussianColorFilter::Make())); + canvas->drawVertices(vertices, SkBlendMode::kModulate, paint); + } +} diff --git a/tests/ShadowUtilsTest.cpp b/tests/ShadowUtilsTest.cpp index 7f9ce91158..e2aa1d117e 100644 --- a/tests/ShadowUtilsTest.cpp +++ b/tests/ShadowUtilsTest.cpp @@ -14,29 +14,29 @@ void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm, bool expectSuccess) { - static constexpr SkScalar kRadius = 2.f; - static constexpr SkColor kUmbraColor = 0xFFFFFFFF; - static constexpr SkColor kPenumbraColor = 0x20202020; - auto verts = - SkShadowTessellator::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor, true); + static constexpr SkScalar kAmbientAlpha = 0.25f; + static constexpr SkScalar kSpotAlpha = 0.25f; + + auto heightFunc = [] (SkScalar, SkScalar) { return 4; }; + + auto verts = SkShadowTessellator::MakeAmbient(path, ctm, heightFunc, kAmbientAlpha, true); if (expectSuccess != SkToBool(verts)) { ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", expectSuccess ? "succeed" : "fail"); } - verts = SkShadowTessellator::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor, - false); + verts = SkShadowTessellator::MakeAmbient(path, ctm, heightFunc, kAmbientAlpha, false); if (expectSuccess != SkToBool(verts)) { ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", expectSuccess ? "succeed" : "fail"); } - verts = SkShadowTessellator::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor, - kPenumbraColor, false); + verts = SkShadowTessellator::MakeSpot(path, ctm, heightFunc, {0, 0, 128}, 128.f, + kSpotAlpha, false); if (expectSuccess != SkToBool(verts)) { ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", expectSuccess ? "succeed" : "fail"); } - verts = SkShadowTessellator::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor, - kPenumbraColor, true); + verts = SkShadowTessellator::MakeSpot(path, ctm, heightFunc, {0, 0, 128}, 128.f, + kSpotAlpha, false); if (expectSuccess != SkToBool(verts)) { ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", expectSuccess ? "succeed" : "fail"); |