diff options
author | Jim Van Verth <jvanverth@google.com> | 2017-07-31 09:34:58 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-07-31 13:55:32 +0000 |
commit | 1af03d4396a9567e3ca127830676eb4fd5a76266 (patch) | |
tree | 985b377567124e1aab52f46609b4e8ea18919caa | |
parent | 0d67fafa3eccc31e5187c740ee19e1c55b135152 (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-x | bench/ShadowBench.cpp | 3 | ||||
-rw-r--r-- | gn/core.gni | 2 | ||||
-rw-r--r-- | gn/tests.gni | 2 | ||||
-rw-r--r-- | include/utils/SkShadowUtils.h | 2 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformCanvas.cpp | 2 | ||||
-rwxr-xr-x | src/core/SkDrawShadowInfo.cpp | 95 | ||||
-rw-r--r-- | src/core/SkDrawShadowInfo.h | 60 | ||||
-rw-r--r-- | src/core/SkDrawShadowRec.h | 25 | ||||
-rw-r--r-- | src/core/SkLiteDL.cpp | 2 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 2 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 2 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 7 | ||||
-rw-r--r-- | src/core/SkRecords.h | 2 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 33 | ||||
-rwxr-xr-x | src/utils/SkShadowTessellator.cpp | 24 | ||||
-rw-r--r-- | src/utils/SkShadowTessellator.h | 2 | ||||
-rw-r--r-- | src/utils/SkShadowUtils.cpp | 2 | ||||
-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); +} |