aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
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 /src/core
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>
Diffstat (limited to 'src/core')
-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
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"