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 /src/core | |
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>
Diffstat (limited to 'src/core')
-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 |
9 files changed, 163 insertions, 34 deletions
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" |