aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-07-31 09:34:58 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-31 13:55:32 +0000
commit1af03d4396a9567e3ca127830676eb4fd5a76266 (patch)
tree985b377567124e1aab52f46609b4e8ea18919caa
parent0d67fafa3eccc31e5187c740ee19e1c55b135152 (diff)
Compute correct bounds for DrawShadowRec.
Bug: skia:6880 Change-Id: Ia8b94e52eec3feb5104d2351bf7a7e6f99101deb Reviewed-on: https://skia-review.googlesource.com/26370 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
-rwxr-xr-xbench/ShadowBench.cpp3
-rw-r--r--gn/core.gni2
-rw-r--r--gn/tests.gni2
-rw-r--r--include/utils/SkShadowUtils.h2
-rw-r--r--src/core/SkColorSpaceXformCanvas.cpp2
-rwxr-xr-xsrc/core/SkDrawShadowInfo.cpp95
-rw-r--r--src/core/SkDrawShadowInfo.h60
-rw-r--r--src/core/SkDrawShadowRec.h25
-rw-r--r--src/core/SkLiteDL.cpp2
-rw-r--r--src/core/SkPicturePlayback.cpp2
-rw-r--r--src/core/SkPictureRecord.cpp2
-rw-r--r--src/core/SkRecordDraw.cpp7
-rw-r--r--src/core/SkRecords.h2
-rw-r--r--src/gpu/GrRenderTargetContext.cpp33
-rwxr-xr-xsrc/utils/SkShadowTessellator.cpp24
-rw-r--r--src/utils/SkShadowTessellator.h2
-rw-r--r--src/utils/SkShadowUtils.cpp2
-rw-r--r--tests/ShadowTest.cpp (renamed from tests/ShadowUtilsTest.cpp)58
18 files changed, 257 insertions, 68 deletions
diff --git a/bench/ShadowBench.cpp b/bench/ShadowBench.cpp
index 82c4f95d4b..f329664fb2 100755
--- a/bench/ShadowBench.cpp
+++ b/bench/ShadowBench.cpp
@@ -6,8 +6,9 @@
*/
#include "Benchmark.h"
#include "SkCanvas.h"
+#include "SkDrawShadowInfo.h"
#include "SkPaint.h"
-#include "SkDrawShadowRec.h"
+#include "SkPath.h"
#include "SkShadowUtils.h"
class ShadowBench : public Benchmark {
diff --git a/gn/core.gni b/gn/core.gni
index ab8824122e..fbb4c7a98a 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -115,6 +115,8 @@ skia_core_sources = [
"$_src/core/SkDrawable.cpp",
"$_src/core/SkDrawLooper.cpp",
"$_src/core/SkDrawProcs.h",
+ "$_src/core/SkDrawShadowInfo.cpp",
+ "$_src/core/SkDrawShadowInfo.h",
"$_src/core/SkEdgeBuilder.cpp",
"$_src/core/SkEdgeBuilder.h",
"$_src/core/SkEdgeClipper.cpp",
diff --git a/gn/tests.gni b/gn/tests.gni
index 16ecb1beb5..03138d5728 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -197,7 +197,7 @@ tests_sources = [
"$_tests/SerializationTest.cpp",
"$_tests/ShaderOpacityTest.cpp",
"$_tests/ShaderTest.cpp",
- "$_tests/ShadowUtilsTest.cpp",
+ "$_tests/ShadowTest.cpp",
"$_tests/SizeTest.cpp",
"$_tests/Sk4x4fTest.cpp",
"$_tests/SkBase64Test.cpp",
diff --git a/include/utils/SkShadowUtils.h b/include/utils/SkShadowUtils.h
index 5409731d37..659908961a 100644
--- a/include/utils/SkShadowUtils.h
+++ b/include/utils/SkShadowUtils.h
@@ -12,7 +12,6 @@
#include "SkPoint3.h"
#include "SkScalar.h"
#include "../private/SkShadowFlags.h"
-#include <functional>
class SkCanvas;
class SkPath;
@@ -106,6 +105,7 @@ public:
*colorScale = adjustedLuminance*(SK_Scalar1 - a);
*tonalAlpha = *colorScale + a;
}
+
};
#endif
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp
index 530552862d..6d6d27b399 100644
--- a/src/core/SkColorSpaceXformCanvas.cpp
+++ b/src/core/SkColorSpaceXformCanvas.cpp
@@ -8,7 +8,7 @@
#include "SkColorFilter.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkColorSpaceXformer.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkGradientShader.h"
#include "SkImageFilter.h"
#include "SkImagePriv.h"
diff --git a/src/core/SkDrawShadowInfo.cpp b/src/core/SkDrawShadowInfo.cpp
new file mode 100755
index 0000000000..704083b428
--- /dev/null
+++ b/src/core/SkDrawShadowInfo.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDrawShadowInfo.h"
+#include "SkMatrix.h"
+#include "SkPath.h"
+#include "SkRect.h"
+
+namespace SkDrawShadowMetrics {
+
+static SkScalar compute_z(SkScalar x, SkScalar y, const SkPoint3& params) {
+ return x*params.fX + y*params.fY + params.fZ;
+}
+
+void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatrix& ctm,
+ SkRect* bounds) {
+ SkRect ambientBounds = path.getBounds();
+ SkScalar occluderZ;
+ if (SkScalarNearlyZero(rec.fZPlaneParams.fX) && SkScalarNearlyZero(rec.fZPlaneParams.fY)) {
+ occluderZ = rec.fZPlaneParams.fZ;
+ } else {
+ occluderZ = compute_z(ambientBounds.fLeft, ambientBounds.fTop, rec.fZPlaneParams);
+ occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fTop,
+ rec.fZPlaneParams));
+ occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fLeft, ambientBounds.fBottom,
+ rec.fZPlaneParams));
+ occluderZ = SkTMax(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fBottom,
+ rec.fZPlaneParams));
+ }
+ SkScalar ambientBlur;
+ SkScalar spotBlur;
+ SkScalar spotScale;
+ SkPoint spotOffset;
+ if (ctm.hasPerspective()) {
+ // transform ambient and spot bounds into device space
+ ctm.mapRect(&ambientBounds);
+
+ // get ambient blur (in device space)
+ ambientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
+
+ // get spot params (in device space)
+ SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
+ ctm.mapPoints(&devLightPos, 1);
+ SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
+ rec.fLightPos.fZ, rec.fLightRadius,
+ &spotBlur, &spotScale, &spotOffset);
+ } else {
+ SkScalar devToSrcScale = SkScalarInvert(ctm.getMinScale());
+
+ // get ambient blur (in local space)
+ SkScalar devSpaceAmbientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
+ ambientBlur = devSpaceAmbientBlur*devToSrcScale;
+
+ // get spot params (in local space)
+ SkDrawShadowMetrics::GetSpotParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
+ rec.fLightPos.fZ, rec.fLightRadius,
+ &spotBlur, &spotScale, &spotOffset);
+
+ // convert spot blur to local space
+ spotBlur *= devToSrcScale;
+ }
+
+ // in both cases, adjust ambient and spot bounds
+ SkRect spotBounds = ambientBounds;
+ ambientBounds.outset(ambientBlur, ambientBlur);
+ spotBounds.fLeft *= spotScale;
+ spotBounds.fTop *= spotScale;
+ spotBounds.fRight *= spotScale;
+ spotBounds.fBottom *= spotScale;
+ spotBounds.offset(spotOffset.fX, spotOffset.fY);
+ spotBounds.outset(spotBlur, spotBlur);
+
+ // merge bounds
+ *bounds = ambientBounds;
+ bounds->join(spotBounds);
+ // outset a bit to account for floating point error
+ bounds->outset(1, 1);
+
+ // if perspective, transform back to src space
+ if (ctm.hasPerspective()) {
+ // TODO: create tighter mapping from dev rect back to src rect
+ SkMatrix inverse;
+ if (ctm.invert(&inverse)) {
+ inverse.mapRect(bounds);
+ }
+ }
+}
+
+
+}
+
diff --git a/src/core/SkDrawShadowInfo.h b/src/core/SkDrawShadowInfo.h
new file mode 100644
index 0000000000..a08256b8cd
--- /dev/null
+++ b/src/core/SkDrawShadowInfo.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDrawShadowInfo_DEFINED
+#define SkDrawShadowInfo_DEFINED
+
+#include "SkColor.h"
+#include "SkPoint.h"
+#include "SkPoint3.h"
+
+class SkMatrix;
+class SkPath;
+struct SkRect;
+
+struct SkDrawShadowRec {
+ SkPoint3 fZPlaneParams;
+ SkPoint3 fLightPos;
+ SkScalar fLightRadius;
+ SkScalar fAmbientAlpha;
+ SkScalar fSpotAlpha;
+ SkColor fColor;
+ uint32_t fFlags;
+};
+
+namespace SkDrawShadowMetrics {
+
+static constexpr auto kAmbientHeightFactor = 1.0f / 128.0f;
+static constexpr auto kAmbientGeomFactor = 64.0f;
+
+inline SkScalar AmbientBlurRadius(SkScalar height) {
+ return height*kAmbientHeightFactor*kAmbientGeomFactor;
+}
+
+inline SkScalar AmbientRecipAlpha(SkScalar height) {
+ return 1.0f + SkTMax(height*kAmbientHeightFactor, 0.0f);
+}
+
+inline SkScalar SpotBlurRadius(SkScalar occluderZ, SkScalar lightZ, SkScalar lightRadius) {
+ return lightRadius*SkTPin(occluderZ / (lightZ - occluderZ), 0.0f, 0.95f);
+}
+
+inline void GetSpotParams(SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ,
+ SkScalar lightRadius,
+ SkScalar* blurRadius, SkScalar* scale, SkVector* translate) {
+ SkScalar zRatio = SkTPin(occluderZ / (lightZ - occluderZ), 0.0f, 0.95f);
+ *blurRadius = lightRadius*zRatio;
+ *scale = SkTMax(lightZ / (lightZ - occluderZ), 1.0f);
+ *translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
+}
+
+// get bounds prior to the ctm being applied
+void GetLocalBounds(const SkPath&, const SkDrawShadowRec&, const SkMatrix& ctm, SkRect* bounds);
+
+}
+
+#endif
diff --git a/src/core/SkDrawShadowRec.h b/src/core/SkDrawShadowRec.h
deleted file mode 100644
index cc55804891..0000000000
--- a/src/core/SkDrawShadowRec.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkDrawShadowRec_DEFINED
-#define SkDrawShadowRec_DEFINED
-
-#include "SkColor.h"
-#include "SkPath.h"
-#include "SkPoint3.h"
-
-struct SkDrawShadowRec {
- SkPoint3 fZPlaneParams;
- SkPoint3 fLightPos;
- SkScalar fLightRadius;
- SkScalar fAmbientAlpha;
- SkScalar fSpotAlpha;
- SkColor fColor;
- uint32_t fFlags;
-};
-
-#endif
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index f1101b1be2..1565dae5cc 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -8,7 +8,7 @@
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDrawFilter.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkImage.h"
#include "SkImageFilter.h"
#include "SkLiteDL.h"
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 1e4fe11b8e..9ebb178aa5 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -6,7 +6,7 @@
*/
#include "SkCanvas.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkPatchUtils.h"
#include "SkPictureData.h"
#include "SkPicturePlayback.h"
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 0e1facaa5f..4421633580 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -6,7 +6,7 @@
*/
#include "SkPictureRecord.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkImage_Base.h"
#include "SkPatchUtils.h"
#include "SkPixelRef.h"
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 1e69e178c2..df68f8a622 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -457,10 +457,9 @@ private:
}
Bounds bounds(const DrawShadowRec& op) const {
- // TODO: compute correct bounds for shadow
- SkRect shadowBounds = op.path.getBounds();
- shadowBounds.outset(100, 100);
- return this->adjustAndMap(shadowBounds, nullptr);
+ SkRect bounds;
+ SkDrawShadowMetrics::GetLocalBounds(op.path, op.rec, fCTM, &bounds);
+ return this->adjustAndMap(bounds, nullptr);
}
Bounds bounds(const DrawPicture& op) const {
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 389730404c..8821a3ea2a 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -11,7 +11,7 @@
#include "SkData.h"
#include "SkCanvas.h"
#include "SkDrawable.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkImage.h"
#include "SkImageFilter.h"
#include "SkMatrix.h"
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 4ec14bccf6..66a707b52d 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -21,7 +21,7 @@
#include "GrResourceProvider.h"
#include "GrStencilAttachment.h"
#include "GrTracing.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkLatticeIter.h"
#include "SkMatrixPriv.h"
#include "SkShadowUtils.h"
@@ -1012,12 +1012,9 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
bool tonalColor = SkToBool(rec.fFlags & SkShadowFlags::kTonalColor_ShadowFlag);
if (rec.fAmbientAlpha > 0) {
- static constexpr float kHeightFactor = 1.0f / 128.0f;
- static constexpr float kGeomFactor = 64.0f;
-
- SkScalar devSpaceInsetWidth = occluderHeight * kHeightFactor * kGeomFactor;
- const float umbraAlpha = (1.0f + SkTMax(occluderHeight * kHeightFactor, 0.0f));
- const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraAlpha;
+ SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
+ const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
+ const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
// Outset the shadow rrect to the border of the penumbra
SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
@@ -1044,8 +1041,8 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
devSpaceInsetWidth = ambientRRect.width();
}
// the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur,
- // which is just 1/umbraAlpha.
- SkScalar blurClamp = SkScalarInvert(umbraAlpha);
+ // which is just 1/umbraRecipAlpha.
+ SkScalar blurClamp = SkScalarInvert(umbraRecipAlpha);
std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(ambientColor, viewMatrix,
ambientRRect,
@@ -1057,15 +1054,15 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
}
if (rec.fSpotAlpha > 0) {
- float zRatio = SkTPin(occluderHeight / (devLightPos.fZ - occluderHeight), 0.0f, 0.95f);
-
- SkScalar devSpaceSpotBlur = 2.0f * rec.fLightRadius * zRatio;
- // handle scale of radius and pad due to CTM
+ SkScalar devSpaceSpotBlur;
+ SkScalar spotScale;
+ SkVector spotOffset;
+ SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
+ devLightPos.fZ, rec.fLightRadius,
+ &devSpaceSpotBlur, &spotScale, &spotOffset);
+ // handle scale of radius due to CTM
const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
- // Compute the scale and translation for the spot shadow.
- const SkScalar spotScale = devLightPos.fZ / (devLightPos.fZ - occluderHeight);
- SkPoint spotOffset = SkPoint::Make(zRatio*(-devLightPos.fX), zRatio*(-devLightPos.fY));
// Adjust translate for the effect of the scale.
spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
@@ -1087,7 +1084,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX;
// Compute the insetWidth
- SkScalar blurOutset = 0.5f*srcSpaceSpotBlur;
+ SkScalar blurOutset = srcSpaceSpotBlur;
SkScalar insetWidth = blurOutset;
if (transparent) {
// If transparent, just do a fill
@@ -1159,7 +1156,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(spotColor, viewMatrix,
spotShadowRRect,
- devSpaceSpotBlur,
+ 2.0f * devSpaceSpotBlur,
insetWidth);
SkASSERT(op);
this->addDrawOp(clip, std::move(op));
diff --git a/src/utils/SkShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp
index 62306998d8..7c49ba6688 100755
--- a/src/utils/SkShadowTessellator.cpp
+++ b/src/utils/SkShadowTessellator.cpp
@@ -7,6 +7,7 @@
#include "SkShadowTessellator.h"
#include "SkColorPriv.h"
+#include "SkDrawShadowInfo.h"
#include "SkGeometry.h"
#include "SkInsetConvexPolygon.h"
#include "SkPath.h"
@@ -345,16 +346,14 @@ private:
void handleLine(const SkPoint& p) override;
void addEdge(const SkVector& nextPoint, const SkVector& nextNormal);
- static constexpr auto kHeightFactor = 1.0f / 128.0f;
- static constexpr auto kGeomFactor = 64.0f;
static constexpr auto kMaxEdgeLenSqr = 20 * 20;
static constexpr auto kInsetFactor = -0.5f;
SkScalar offset(SkScalar z) {
- return z * kHeightFactor * kGeomFactor;
+ return SkDrawShadowMetrics::AmbientBlurRadius(z);
}
SkColor umbraColor(SkScalar z) {
- SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(z*kHeightFactor, 0.0f)));
+ SkScalar umbraAlpha = SkScalarInvert(SkDrawShadowMetrics::AmbientRecipAlpha(z));
return SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0);
}
@@ -373,8 +372,7 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
, fSplitFirstEdge(false)
, fSplitPreviousEdge(false) {
// Set base colors
- SkScalar occluderHeight = heightFunc(0, 0);
- SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(occluderHeight*kHeightFactor, 0.0f)));
+ SkScalar umbraAlpha = SkScalarInvert(SkDrawShadowMetrics::AmbientRecipAlpha(heightFunc(0, 0)));
// 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
@@ -804,17 +802,17 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
// Set radius and colors
SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
SkScalar occluderHeight = this->heightFunc(center.fX, center.fY) + fZOffset;
- float zRatio = SkTPin(occluderHeight / (fLightZ - occluderHeight), 0.0f, 0.95f);
- SkScalar radius = lightRadius * zRatio;
- fRadius = radius;
fUmbraColor = SkColorSetARGB(255, 0, 0, 0);
fPenumbraColor = SkColorSetARGB(0, 0, 0, 0);
- // Compute the scale and translation for the spot shadow.
+ // Compute the blur radius, scale and translation for the spot shadow.
+ SkScalar radius;
SkMatrix shadowTransform;
if (!ctm.hasPerspective()) {
- SkScalar scale = fLightZ / (fLightZ - occluderHeight);
- SkVector translate = SkVector::Make(-zRatio * lightPos.fX, -zRatio * lightPos.fY);
+ SkScalar scale;
+ SkVector translate;
+ SkDrawShadowMetrics::GetSpotParams(occluderHeight, lightPos.fX, lightPos.fY, fLightZ,
+ lightRadius, &radius, &scale, &translate);
shadowTransform.setScaleTranslate(scale, scale, translate.fX, translate.fY);
} else {
// For perspective, we have a scale, a z-shear, and another projective divide --
@@ -823,7 +821,9 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
shadowTransform.reset();
// Also can't cull the center (for now).
fTransparent = true;
+ radius = SkDrawShadowMetrics::SpotBlurRadius(occluderHeight, lightPos.fZ, lightRadius);
}
+ fRadius = radius;
SkMatrix fullTransform = SkMatrix::Concat(shadowTransform, ctm);
// Set up our reverse mapping
diff --git a/src/utils/SkShadowTessellator.h b/src/utils/SkShadowTessellator.h
index 420b8184ef..4aecf1d3b1 100644
--- a/src/utils/SkShadowTessellator.h
+++ b/src/utils/SkShadowTessellator.h
@@ -36,6 +36,8 @@ sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm,
*/
sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, const SkPoint3& zPlane,
const SkPoint3& lightPos, SkScalar lightRadius, bool transparent);
+
+
}
#endif
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index ceeb191f10..b6c57f370e 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -10,7 +10,7 @@
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkDevice.h"
-#include "SkDrawShadowRec.h"
+#include "SkDrawShadowInfo.h"
#include "SkPath.h"
#include "SkPM4f.h"
#include "SkRandom.h"
diff --git a/tests/ShadowUtilsTest.cpp b/tests/ShadowTest.cpp
index c0e20d57e4..8a921d8bc8 100644
--- a/tests/ShadowUtilsTest.cpp
+++ b/tests/ShadowTest.cpp
@@ -6,6 +6,7 @@
*/
#include "SkCanvas.h"
+#include "SkDrawShadowInfo.h"
#include "SkPath.h"
#include "SkShadowTessellator.h"
#include "SkShadowUtils.h"
@@ -58,3 +59,60 @@ DEF_TEST(ShadowUtils, reporter) {
}
tessellate_shadow(reporter, path, canvas.getTotalMatrix(), false);
}
+
+void check_xformed_bounds(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm) {
+ const SkDrawShadowRec rec = {
+ SkPoint3::Make(0, 0, 4),
+ SkPoint3::Make(100, 0, 600),
+ 800.f,
+ 0.035f,
+ 0.25f,
+ SK_ColorBLACK,
+ 0
+ };
+ SkRect bounds;
+ SkDrawShadowMetrics::GetLocalBounds(path, rec, ctm, &bounds);
+ ctm.mapRect(&bounds);
+
+ auto verts = SkShadowTessellator::MakeAmbient(path, ctm, rec.fZPlaneParams, true);
+ if (verts) {
+ REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
+ }
+
+ SkPoint mapXY = ctm.mapXY(rec.fLightPos.fX, rec.fLightPos.fY);
+ SkPoint3 devLightPos = SkPoint3::Make(mapXY.fX, mapXY.fY, rec.fLightPos.fZ);
+ verts = SkShadowTessellator::MakeSpot(path, ctm, rec.fZPlaneParams, devLightPos,
+ rec.fLightRadius, false);
+ if (verts) {
+ REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
+ }
+}
+
+void check_bounds(skiatest::Reporter* reporter, const SkPath& path) {
+ SkMatrix ctm;
+ ctm.setTranslate(100, 100);
+ check_xformed_bounds(reporter, path, ctm);
+ ctm.postScale(2, 2);
+ check_xformed_bounds(reporter, path, ctm);
+ ctm.preRotate(45);
+ check_xformed_bounds(reporter, path, ctm);
+ ctm.preSkew(40, -20);
+ check_xformed_bounds(reporter, path, ctm);
+ ctm[SkMatrix::kMPersp0] = 0.0001f;
+ ctm[SkMatrix::kMPersp1] = 12.f;
+ check_xformed_bounds(reporter, path, ctm);
+}
+
+DEF_TEST(ShadowBounds, reporter) {
+ SkPath path;
+ path.addRRect(SkRRect::MakeRectXY(SkRect::MakeLTRB(-50, -20, 40, 30), 4, 4));
+ check_bounds(reporter, path);
+
+ path.reset();
+ path.addOval(SkRect::MakeLTRB(300, 300, 900, 900));
+ check_bounds(reporter, path);
+
+ path.reset();
+ path.cubicTo(100, 50, 20, 100, 0, 0);
+ check_bounds(reporter, path);
+}