diff options
author | Jim Van Verth <jvanverth@google.com> | 2017-05-18 15:06:54 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-18 19:45:45 +0000 |
commit | 3af1af9e979552cf2e3b22feb1de5aeba810fc4e (patch) | |
tree | 20bfe9c69557b91e42d77920d2625a0eaa3efc8d | |
parent | 7f1ce29c9bb9be8b2d8dbf9a99f14f74d5dc6d80 (diff) |
Remove ambient and spot mask filters.
Also remove a deprecated interface in SkShadowUtils.
Change-Id: I32e67271be953f11071c512cb39a47ea1e7dcaaf
Reviewed-on: https://skia-review.googlesource.com/17266
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r-- | gn/effects.gni | 5 | ||||
-rw-r--r-- | include/utils/SkShadowUtils.h | 38 | ||||
-rw-r--r-- | src/effects/shadows/SkAmbientShadowMaskFilter.cpp | 271 | ||||
-rw-r--r-- | src/effects/shadows/SkAmbientShadowMaskFilter.h | 33 | ||||
-rw-r--r-- | src/effects/shadows/SkSpotShadowMaskFilter.cpp | 356 | ||||
-rw-r--r-- | src/effects/shadows/SkSpotShadowMaskFilter.h | 37 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 216 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 24 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 24 | ||||
-rw-r--r-- | src/utils/SkShadowUtils.cpp | 64 |
10 files changed, 233 insertions, 835 deletions
diff --git a/gn/effects.gni b/gn/effects.gni index df8e75b144..278925ba85 100644 --- a/gn/effects.gni +++ b/gn/effects.gni @@ -86,11 +86,6 @@ skia_effects_sources = [ "$_src/effects/gradients/SkSweepGradient.cpp", "$_src/effects/gradients/SkSweepGradient.h", - "$_src/effects/shadows/SkAmbientShadowMaskFilter.cpp", - "$_src/effects/shadows/SkAmbientShadowMaskFilter.h", - "$_src/effects/shadows/SkSpotShadowMaskFilter.cpp", - "$_src/effects/shadows/SkSpotShadowMaskFilter.h", - "$_include/effects/Sk1DPathEffect.h", "$_include/effects/Sk2DPathEffect.h", "$_include/effects/SkAlphaThresholdFilter.h", diff --git a/include/utils/SkShadowUtils.h b/include/utils/SkShadowUtils.h index 2385a48075..838a12bba8 100644 --- a/include/utils/SkShadowUtils.h +++ b/include/utils/SkShadowUtils.h @@ -46,7 +46,7 @@ public: * Draw an offset spot shadow and outlining ambient shadow for the given path using a disc * light. * - * Deprecated version with height value (to be removed when Android and Flutter are updated). + * Deprecated version with height value (to be removed when Flutter is updated). * * @param canvas The canvas on which to draw the shadows. * @param path The occluder used to generate the shadows. @@ -69,42 +69,6 @@ public: DrawShadow(canvas, path, zPlane, lightPos, lightRadius, ambientAlpha, spotAlpha, color, flags); } - -#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK - /** - * 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 local x and y position. - * This shadow will not be cached, as the assumption is that this will be used for animation. - * - * Deprecated (to be removed when Android is updated). - * - * @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) { - SkPoint3 zPlane; - zPlane.fZ = heightFunc(0, 0); - zPlane.fX = heightFunc(1, 0) - zPlane.fZ; - zPlane.fY = heightFunc(0, 1) - zPlane.fZ; - - DrawShadow(canvas, path, zPlane, lightPos, lightRadius, ambientAlpha, spotAlpha, - color, flags); - } -#endif }; #endif diff --git a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp deleted file mode 100644 index 66218cd96f..0000000000 --- a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp +++ /dev/null @@ -1,271 +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. - */ - -#include "SkAmbientShadowMaskFilter.h" -#include "SkReadBuffer.h" -#include "SkStringUtils.h" -#include "SkWriteBuffer.h" - -#if SK_SUPPORT_GPU -#include "GrContext.h" -#include "GrRenderTargetContext.h" -#include "GrFragmentProcessor.h" -#include "GrStyle.h" -#include "GrTexture.h" -#include "GrTextureProxy.h" -#include "SkStrokeRec.h" -#endif - -class SkAmbientShadowMaskFilterImpl : public SkMaskFilter { -public: - SkAmbientShadowMaskFilterImpl(SkScalar occluderHeight, SkScalar ambientAlpha, uint32_t flags); - - // overrides from SkMaskFilter - SkMask::Format getFormat() const override; - bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, - SkIPoint* margin) const override; - -#if SK_SUPPORT_GPU - bool canFilterMaskGPU(const SkRRect& devRRect, - const SkIRect& clipBounds, - const SkMatrix& ctm, - SkRect* maskRect) const override; - bool directFilterMaskGPU(GrContext*, - GrRenderTargetContext* drawContext, - GrPaint&&, - const GrClip&, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkPath& path) const override; - bool directFilterRRectMaskGPU(GrContext*, - GrRenderTargetContext* drawContext, - GrPaint&&, - const GrClip&, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkRRect& rrect, - const SkRRect& devRRect) const override; - sk_sp<GrTextureProxy> filterMaskGPU(GrContext*, - sk_sp<GrTextureProxy> srcProxy, - const SkMatrix& ctm, - const SkIRect& maskRect) const override; -#endif - - void computeFastBounds(const SkRect&, SkRect*) const override; - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAmbientShadowMaskFilterImpl) - -private: - SkScalar fOccluderHeight; - SkScalar fAmbientAlpha; - uint32_t fFlags; - - SkAmbientShadowMaskFilterImpl(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - - friend class SkAmbientShadowMaskFilter; - - typedef SkMaskFilter INHERITED; -}; - -sk_sp<SkMaskFilter> SkAmbientShadowMaskFilter::Make(SkScalar occluderHeight, SkScalar ambientAlpha, - uint32_t flags) { - // add some param checks here for early exit - - return sk_sp<SkMaskFilter>(new SkAmbientShadowMaskFilterImpl(occluderHeight, ambientAlpha, - flags)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -SkAmbientShadowMaskFilterImpl::SkAmbientShadowMaskFilterImpl(SkScalar occluderHeight, - SkScalar ambientAlpha, - uint32_t flags) - : fOccluderHeight(occluderHeight) - , fAmbientAlpha(ambientAlpha) - , fFlags(flags) { - SkASSERT(fOccluderHeight > 0); - SkASSERT(fAmbientAlpha >= 0); -} - -SkMask::Format SkAmbientShadowMaskFilterImpl::getFormat() const { - return SkMask::kA8_Format; -} - -bool SkAmbientShadowMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, - const SkMatrix& matrix, - SkIPoint* margin) const { - // TODO something - return false; -} - -void SkAmbientShadowMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const { - // TODO compute based on ambient data - dst->set(src.fLeft, src.fTop, src.fRight, src.fBottom); -} - -sk_sp<SkFlattenable> SkAmbientShadowMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { - const SkScalar occluderHeight = buffer.readScalar(); - const SkScalar ambientAlpha = buffer.readScalar(); - const uint32_t flags = buffer.readUInt(); - - return SkAmbientShadowMaskFilter::Make(occluderHeight, ambientAlpha, flags); -} - -void SkAmbientShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { - buffer.writeScalar(fOccluderHeight); - buffer.writeScalar(fAmbientAlpha); - buffer.writeUInt(fFlags); -} - -#if SK_SUPPORT_GPU - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -bool SkAmbientShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, - const SkIRect& clipBounds, - const SkMatrix& ctm, - SkRect* maskRect) const { - // TODO - *maskRect = devRRect.rect(); - return true; -} - -static const float kHeightFactor = 1.0f / 128.0f; -static const float kGeomFactor = 64.0f; - -bool SkAmbientShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context, - GrRenderTargetContext* rtContext, - GrPaint&& paint, - const GrClip& clip, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkPath& path) const { - SkASSERT(rtContext); - // TODO: this will not handle local coordinates properly - - SkRect rect; - SkRRect rrect; - if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), - rect.height())) { - rrect = SkRRect::MakeOval(rect); - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } else if (path.isRect(&rect)) { - rrect = SkRRect::MakeRect(rect); - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } else if (path.isRRect(&rrect) && rrect.isSimpleCircular()) { - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } - - return false; -} - -bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*, - GrRenderTargetContext* rtContext, - GrPaint&& paint, - const GrClip& clip, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkRRect& rrect, - const SkRRect& devRRect) const { - // Fast path only supports filled rrects for now. - // TODO: fill and stroke as well. - if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) { - return false; - } - // These should have been checked by the caller. - // Fast path only supports simple rrects with circular corners. - SkASSERT(devRRect.isRect() || devRRect.isCircle() || - (devRRect.isSimple() && devRRect.allCornersCircular())); - // Fast path only supports uniform scale. - SkASSERT(viewMatrix.isSimilarity()); - // Assume we have positive alpha - SkASSERT(fAmbientAlpha > 0); - - // 1/scale - SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ? - SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) : - sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] + - viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]); - - SkScalar devSpaceInsetWidth = fOccluderHeight * kHeightFactor * kGeomFactor; - const float umbraAlpha = (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f)); - const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraAlpha; - - // Outset the shadow rrect to the border of the penumbra - SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale; - SkRRect ambientRRect; - SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset); - // If the rrect was an oval then its outset will also be one. - // We set it explicitly to avoid errors. - if (rrect.isOval()) { - ambientRRect = SkRRect::MakeOval(outsetRect); - } else { - SkScalar outsetRad = rrect.getSimpleRadii().fX + ambientPathOutset; - ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); - } - - GrPaint newPaint(paint); - GrColor4f color = newPaint.getColor4f(); - newPaint.setColor4f(color.mulByScalar(fAmbientAlpha)); - if (SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag)) { - // set a large inset to force a fill - devSpaceInsetWidth = ambientRRect.width(); - } - - // the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur, - // which is just 1/umbraAlpha. - SkScalar blurClamp = SkScalarInvert(umbraAlpha); - rtContext->drawShadowRRect(clip, std::move(newPaint), viewMatrix, ambientRRect, - devSpaceAmbientBlur, devSpaceInsetWidth, - blurClamp); - - return true; -} - -sk_sp<GrTextureProxy> SkAmbientShadowMaskFilterImpl::filterMaskGPU(GrContext*, - sk_sp<GrTextureProxy> srcProxy, - const SkMatrix& ctm, - const SkIRect& maskRect) const { - // This filter is generative and doesn't operate on pre-existing masks - return nullptr; -} - -#endif // SK_SUPPORT_GPU - -#ifndef SK_IGNORE_TO_STRING -void SkAmbientShadowMaskFilterImpl::toString(SkString* str) const { - str->append("SkAmbientShadowMaskFilterImpl: ("); - - str->append("occluderHeight: "); - str->appendScalar(fOccluderHeight); - str->append(" "); - - str->append("ambientAlpha: "); - str->appendScalar(fAmbientAlpha); - str->append(" "); - - str->append("flags: ("); - if (fFlags) { - bool needSeparator = false; - SkAddFlagToString(str, - SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag), - "TransparentOccluder", &needSeparator); - } else { - str->append("None"); - } - str->append("))"); -} -#endif - -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAmbientShadowMaskFilter) -SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAmbientShadowMaskFilterImpl) -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END diff --git a/src/effects/shadows/SkAmbientShadowMaskFilter.h b/src/effects/shadows/SkAmbientShadowMaskFilter.h deleted file mode 100644 index cd77b106a4..0000000000 --- a/src/effects/shadows/SkAmbientShadowMaskFilter.h +++ /dev/null @@ -1,33 +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 SkAmbientShadowMaskFilter_DEFINED -#define SkAmbientShadowMaskFilter_DEFINED - -#include "SkMaskFilter.h" -#include "SkShadowFlags.h" - -/* - * This filter implements a shadow representing ambient occlusion for an occluding object. - */ -class SK_API SkAmbientShadowMaskFilter { -public: - /** Create a shadow maskfilter. - * @param occluderHeight Height of occluding object off of ground plane. - * @param ambientAlpha Base opacity of the ambient occlusion shadow. - * @param flags Flags to use - defaults to none - * @return The new shadow maskfilter - */ - static sk_sp<SkMaskFilter> Make(SkScalar occluderHeight, SkScalar ambientAlpha, - uint32_t flags = SkShadowFlags::kNone_ShadowFlag); - - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() - -private: - SkAmbientShadowMaskFilter(); // can't be instantiated -}; -#endif diff --git a/src/effects/shadows/SkSpotShadowMaskFilter.cpp b/src/effects/shadows/SkSpotShadowMaskFilter.cpp deleted file mode 100644 index a51aa56632..0000000000 --- a/src/effects/shadows/SkSpotShadowMaskFilter.cpp +++ /dev/null @@ -1,356 +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. - */ - -#include "SkSpotShadowMaskFilter.h" -#include "SkReadBuffer.h" -#include "SkStringUtils.h" -#include "SkWriteBuffer.h" - -#if SK_SUPPORT_GPU -#include "GrContext.h" -#include "GrRenderTargetContext.h" -#include "GrFragmentProcessor.h" -#include "GrStyle.h" -#include "GrTexture.h" -#include "GrTextureProxy.h" -#include "SkStrokeRec.h" -#endif - -class SkSpotShadowMaskFilterImpl : public SkMaskFilter { -public: - SkSpotShadowMaskFilterImpl(SkScalar occluderHeight, const SkPoint3& lightPos, - SkScalar lightRadius, SkScalar spotAlpha, uint32_t flags); - - // overrides from SkMaskFilter - SkMask::Format getFormat() const override; - bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, - SkIPoint* margin) const override; - -#if SK_SUPPORT_GPU - bool canFilterMaskGPU(const SkRRect& devRRect, - const SkIRect& clipBounds, - const SkMatrix& ctm, - SkRect* maskRect) const override; - bool directFilterMaskGPU(GrContext*, - GrRenderTargetContext* drawContext, - GrPaint&&, - const GrClip&, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkPath& path) const override; - bool directFilterRRectMaskGPU(GrContext*, - GrRenderTargetContext* drawContext, - GrPaint&&, - const GrClip&, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkRRect& rrect, - const SkRRect& devRRect) const override; - sk_sp<GrTextureProxy> filterMaskGPU(GrContext*, - sk_sp<GrTextureProxy> srcProxy, - const SkMatrix& ctm, - const SkIRect& maskRect) const override; -#endif - - void computeFastBounds(const SkRect&, SkRect*) const override; - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotShadowMaskFilterImpl) - -private: - SkScalar fOccluderHeight; - SkPoint3 fLightPos; - SkScalar fLightRadius; - SkScalar fSpotAlpha; - uint32_t fFlags; - - SkSpotShadowMaskFilterImpl(SkReadBuffer&); - void flatten(SkWriteBuffer&) const override; - - friend class SkSpotShadowMaskFilter; - - typedef SkMaskFilter INHERITED; -}; - -sk_sp<SkMaskFilter> SkSpotShadowMaskFilter::Make(SkScalar occluderHeight, const SkPoint3& lightPos, - SkScalar lightRadius, SkScalar spotAlpha, - uint32_t flags) { - // add some param checks here for early exit - - return sk_sp<SkMaskFilter>(new SkSpotShadowMaskFilterImpl(occluderHeight, lightPos, - lightRadius, spotAlpha, flags)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -SkSpotShadowMaskFilterImpl::SkSpotShadowMaskFilterImpl(SkScalar occluderHeight, - const SkPoint3& lightPos, - SkScalar lightRadius, - SkScalar spotAlpha, - uint32_t flags) - : fOccluderHeight(occluderHeight) - , fLightPos(lightPos) - , fLightRadius(lightRadius) - , fSpotAlpha(spotAlpha) - , fFlags(flags) { - SkASSERT(fOccluderHeight > 0); - SkASSERT(fLightPos.z() > 0 && fLightPos.z() > fOccluderHeight); - SkASSERT(fLightRadius > 0); - SkASSERT(fSpotAlpha >= 0); -} - -SkMask::Format SkSpotShadowMaskFilterImpl::getFormat() const { - return SkMask::kA8_Format; -} - -bool SkSpotShadowMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, - const SkMatrix& matrix, - SkIPoint* margin) const { - // TODO something - return false; -} - -void SkSpotShadowMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const { - // TODO compute based on ambient + spot data - dst->set(src.fLeft, src.fTop, src.fRight, src.fBottom); -} - -sk_sp<SkFlattenable> SkSpotShadowMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { - const SkScalar occluderHeight = buffer.readScalar(); - const SkScalar lightX = buffer.readScalar(); - const SkScalar lightY = buffer.readScalar(); - const SkScalar lightZ = buffer.readScalar(); - const SkPoint3 lightPos = SkPoint3::Make(lightX, lightY, lightZ); - const SkScalar lightRadius = buffer.readScalar(); - const SkScalar spotAlpha = buffer.readScalar(); - const uint32_t flags = buffer.readUInt(); - - return SkSpotShadowMaskFilter::Make(occluderHeight, lightPos, lightRadius, - spotAlpha, flags); -} - -void SkSpotShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { - buffer.writeScalar(fOccluderHeight); - buffer.writeScalar(fLightPos.fX); - buffer.writeScalar(fLightPos.fY); - buffer.writeScalar(fLightPos.fZ); - buffer.writeScalar(fLightRadius); - buffer.writeScalar(fSpotAlpha); - buffer.writeUInt(fFlags); -} - -#if SK_SUPPORT_GPU - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -bool SkSpotShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, - const SkIRect& clipBounds, - const SkMatrix& ctm, - SkRect* maskRect) const { - // TODO - *maskRect = devRRect.rect(); - return true; -} - -bool SkSpotShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context, - GrRenderTargetContext* rtContext, - GrPaint&& paint, - const GrClip& clip, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkPath& path) const { - SkASSERT(rtContext); - // TODO: this will not handle local coordinates properly - - SkRect rect; - SkRRect rrect; - if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), - rect.height())) { - rrect = SkRRect::MakeOval(rect); - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } else if (path.isRect(&rect)) { - rrect = SkRRect::MakeRect(rect); - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } else if (path.isRRect(&rrect) && rrect.isSimpleCircular()) { - return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, - SkMatrix::I(), strokeRec, rrect, rrect); - } - - return false; -} - -bool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*, - GrRenderTargetContext* rtContext, - GrPaint&& paint, - const GrClip& clip, - const SkMatrix& viewMatrix, - const SkStrokeRec& strokeRec, - const SkRRect& rrect, - const SkRRect& devRRect) const { - // Fast path only supports filled rrects for now. - // TODO: fill and stroke as well. - if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) { - return false; - } - // These should have been checked by the caller. - // Fast path only supports simple rrects with circular corners. - SkASSERT(devRRect.isRect() || devRRect.isCircle() || - (devRRect.isSimple() && devRRect.allCornersCircular())); - // Fast path only supports uniform scale. - SkASSERT(viewMatrix.isSimilarity()); - // Assume we have positive alpha - SkASSERT(fSpotAlpha > 0); - - // 1/scale - SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ? - SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) : - sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] + - viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]); - - float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f); - - SkScalar devSpaceSpotBlur = 2.0f * fLightRadius * zRatio; - // handle scale of radius and pad due to CTM - const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale; - - // Compute the scale and translation for the spot shadow. - const SkScalar spotScale = fLightPos.fZ / (fLightPos.fZ - fOccluderHeight); - SkPoint spotOffset = SkPoint::Make(zRatio*(-fLightPos.fX), zRatio*(-fLightPos.fY)); - // Adjust translate for the effect of the scale. - spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX]; - spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY]; - // This offset is in dev space, need to transform it into source space. - SkMatrix ctmInverse; - if (!viewMatrix.invert(&ctmInverse)) { - // Since the matrix is a similarity, this should never happen, but just in case... - SkDebugf("Matrix is degenerate. Will not render spot shadow!\n"); - return true; - } - ctmInverse.mapPoints(&spotOffset, 1); - - // Compute the transformed shadow rrect - SkRRect spotShadowRRect; - SkMatrix shadowTransform; - shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY); - rrect.transform(shadowTransform, &spotShadowRRect); - SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX; - - // Compute the insetWidth - SkScalar blurOutset = 0.5f*srcSpaceSpotBlur; - SkScalar insetWidth = blurOutset; - if (fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag) { - // If transparent, just do a fill - insetWidth += spotShadowRRect.width(); - } else { - // For shadows, instead of using a stroke we specify an inset from the penumbra - // border. We want to extend this inset area so that it meets up with the caster - // geometry. The inset geometry will by default already be inset by the blur width. - // - // We compare the min and max corners inset by the radius between the original - // rrect and the shadow rrect. The distance between the two plus the difference - // between the scaled radius and the original radius gives the distance from the - // transformed shadow shape to the original shape in that corner. The max - // of these gives the maximum distance we need to cover. - // - // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to - // that to get the full insetWidth. - SkScalar maxOffset; - if (rrect.isRect()) { - // Manhattan distance works better for rects - maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft - - rrect.rect().fLeft), - SkTAbs(spotShadowRRect.rect().fTop - - rrect.rect().fTop)), - SkTMax(SkTAbs(spotShadowRRect.rect().fRight - - rrect.rect().fRight), - SkTAbs(spotShadowRRect.rect().fBottom - - rrect.rect().fBottom))); - } else { - SkScalar dr = spotRadius - rrect.getSimpleRadii().fX; - SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft - - rrect.rect().fLeft + dr, - spotShadowRRect.rect().fTop - - rrect.rect().fTop + dr); - SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight - - rrect.rect().fRight - dr, - spotShadowRRect.rect().fBottom - - rrect.rect().fBottom - dr); - maxOffset = SkScalarSqrt(SkTMax(upperLeftOffset.lengthSqd(), - lowerRightOffset.lengthSqd())) + dr; - } - insetWidth += maxOffset; - } - - // Outset the shadow rrect to the border of the penumbra - SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset); - if (spotShadowRRect.isOval()) { - spotShadowRRect = SkRRect::MakeOval(outsetRect); - } else { - SkScalar outsetRad = spotRadius + blurOutset; - spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); - } - - GrColor4f color = paint.getColor4f(); - paint.setColor4f(color.mulByScalar(fSpotAlpha)); - rtContext->drawShadowRRect(clip, std::move(paint), viewMatrix, spotShadowRRect, - devSpaceSpotBlur, insetWidth); - - return true; -} - -sk_sp<GrTextureProxy> SkSpotShadowMaskFilterImpl::filterMaskGPU(GrContext*, - sk_sp<GrTextureProxy> srcProxy, - const SkMatrix& ctm, - const SkIRect& maskRect) const { - // This filter is generative and doesn't operate on pre-existing masks - return nullptr; -} - -#endif - -#ifndef SK_IGNORE_TO_STRING -void SkSpotShadowMaskFilterImpl::toString(SkString* str) const { - str->append("SkSpotShadowMaskFilterImpl: ("); - - str->append("occluderHeight: "); - str->appendScalar(fOccluderHeight); - str->append(" "); - - str->append("lightPos: ("); - str->appendScalar(fLightPos.fX); - str->append(", "); - str->appendScalar(fLightPos.fY); - str->append(", "); - str->appendScalar(fLightPos.fZ); - str->append(") "); - - str->append("lightRadius: "); - str->appendScalar(fLightRadius); - str->append(" "); - - str->append("spotAlpha: "); - str->appendScalar(fSpotAlpha); - str->append(" "); - - str->append("flags: ("); - if (fFlags) { - bool needSeparator = false; - SkAddFlagToString(str, - SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag), - "TransparentOccluder", &needSeparator); - } else { - str->append("None"); - } - str->append("))"); -} -#endif - -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkSpotShadowMaskFilter) -SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotShadowMaskFilterImpl) -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END diff --git a/src/effects/shadows/SkSpotShadowMaskFilter.h b/src/effects/shadows/SkSpotShadowMaskFilter.h deleted file mode 100644 index 5e1a4a9ec9..0000000000 --- a/src/effects/shadows/SkSpotShadowMaskFilter.h +++ /dev/null @@ -1,37 +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 SkSpotShadowMaskFilter_DEFINED -#define SkSpotShadowMaskFilter_DEFINED - -#include "SkMaskFilter.h" -#include "SkShadowFlags.h" - -/* - * This filter implements a shadow for an occluding object - * representing a displaced shadow from a point light. - */ -class SK_API SkSpotShadowMaskFilter { -public: - /** Create a shadow maskfilter. - * @param occluderHeight Height of occluding object off of ground plane. - * @param lightPos Position of the light applied to this object. - * @param lightRadius Radius of the light (light is assumed to be spherical). - * @param spotAlpha Base opacity of the displaced spot shadow. - * @param flags Flags to use - defaults to none - * @return The new shadow maskfilter - */ - static sk_sp<SkMaskFilter> Make(SkScalar occluderHeight, const SkPoint3& lightPos, - SkScalar lightRadius, SkScalar spotAlpha, - uint32_t flags = SkShadowFlags::kNone_ShadowFlag); - - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() - -private: - SkSpotShadowMaskFilter(); // can't be instantiated -}; -#endif diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 1fcb0aadc1..8232f09303 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -7,6 +7,7 @@ #include "GrRenderTargetContext.h" #include "../private/GrAuditTrail.h" +#include "../private/SkShadowFlags.h" #include "GrAppliedClip.h" #include "GrColor.h" #include "GrContextPriv.h" @@ -20,6 +21,7 @@ #include "GrRenderTargetPriv.h" #include "GrResourceProvider.h" #include "GrStencilAttachment.h" +#include "SkDrawShadowRec.h" #include "SkLatticeIter.h" #include "SkMatrixPriv.h" #include "SkSurfacePriv.h" @@ -977,32 +979,210 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip, /////////////////////////////////////////////////////////////////////////////// -void GrRenderTargetContext::drawShadowRRect(const GrClip& clip, - GrPaint&& paint, - const SkMatrix& viewMatrix, - const SkRRect& rrect, - SkScalar blurWidth, - SkScalar insetWidth, - SkScalar blurClamp) { +static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) { + SkPoint3 result; + m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX); + result.fZ = pt.fZ; + return result; +} + +bool GrRenderTargetContext::drawFastShadow(const GrClip& clip, + GrPaint&& paint, + const SkMatrix& viewMatrix, + const SkPath& path, + const SkDrawShadowRec& rec) { ASSERT_SINGLE_OWNER - RETURN_IF_ABANDONED + if (this->drawingManager()->wasAbandoned()) { + return true; + } SkDEBUGCODE(this->validate();) - GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect"); + GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawFastShadow"); + + // check z plane + bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) || + !SkScalarNearlyZero(rec.fZPlaneParams.fY)); + bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag); + if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) { + return false; + } + + SkRRect rrect; + SkRect rect; + // we can only handle rects, circles, and rrects with circular corners + bool isRRect = path.isRRect(&rrect) && rrect.isSimpleCircular() && + rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero; + if (!isRRect && + path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) && + rect.width() > SK_ScalarNearlyZero) { + rrect.setOval(rect); + isRRect = true; + } + if (!isRRect && path.isRect(&rect)) { + rrect.setRect(rect); + isRRect = true; + } + + if (!isRRect) { + return false; + } + if (rrect.isEmpty()) { - return; + return true; } AutoCheckFlush acf(this->drawingManager()); - // TODO: add instancing support? - std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(paint.getColor(), viewMatrix, - rrect, blurWidth, insetWidth, - blurClamp); - if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone); - this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op)); - return; + // transform light + SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos); + + // 1/scale + SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ? + SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) : + sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] + + viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]); + + SkScalar occluderHeight = rec.fZPlaneParams.fZ; + GrColor4f color = paint.getColor4f(); + bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_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; + + // Outset the shadow rrect to the border of the penumbra + SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale; + SkRRect ambientRRect; + SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset); + // If the rrect was an oval then its outset will also be one. + // We set it explicitly to avoid errors. + if (rrect.isOval()) { + ambientRRect = SkRRect::MakeOval(outsetRect); + } else { + SkScalar outsetRad = rrect.getSimpleRadii().fX + ambientPathOutset; + ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); + } + + GrColor ambientColor = color.mulByScalar(rec.fAmbientAlpha).toGrColor(); + if (transparent) { + // set a large inset to force a fill + devSpaceInsetWidth = ambientRRect.width(); + } + // the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur, + // which is just 1/umbraAlpha. + SkScalar blurClamp = SkScalarInvert(umbraAlpha); + + std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(ambientColor, viewMatrix, + ambientRRect, + devSpaceAmbientBlur, + devSpaceInsetWidth, + blurClamp); + if (op) { + GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone); + this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op)); + } } + + 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 + 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]; + // This offset is in dev space, need to transform it into source space. + SkMatrix ctmInverse; + if (viewMatrix.invert(&ctmInverse)) { + ctmInverse.mapPoints(&spotOffset, 1); + } else { + // Since the matrix is a similarity, this should never happen, but just in case... + SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n"); + SkASSERT(false); + } + + // Compute the transformed shadow rrect + SkRRect spotShadowRRect; + SkMatrix shadowTransform; + shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY); + rrect.transform(shadowTransform, &spotShadowRRect); + SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX; + + // Compute the insetWidth + SkScalar blurOutset = 0.5f*srcSpaceSpotBlur; + SkScalar insetWidth = blurOutset; + if (transparent) { + // If transparent, just do a fill + insetWidth += spotShadowRRect.width(); + } else { + // For shadows, instead of using a stroke we specify an inset from the penumbra + // border. We want to extend this inset area so that it meets up with the caster + // geometry. The inset geometry will by default already be inset by the blur width. + // + // We compare the min and max corners inset by the radius between the original + // rrect and the shadow rrect. The distance between the two plus the difference + // between the scaled radius and the original radius gives the distance from the + // transformed shadow shape to the original shape in that corner. The max + // of these gives the maximum distance we need to cover. + // + // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to + // that to get the full insetWidth. + SkScalar maxOffset; + if (rrect.isRect()) { + // Manhattan distance works better for rects + maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft - + rrect.rect().fLeft), + SkTAbs(spotShadowRRect.rect().fTop - + rrect.rect().fTop)), + SkTMax(SkTAbs(spotShadowRRect.rect().fRight - + rrect.rect().fRight), + SkTAbs(spotShadowRRect.rect().fBottom - + rrect.rect().fBottom))); + } else { + SkScalar dr = spotRadius - rrect.getSimpleRadii().fX; + SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft - + rrect.rect().fLeft + dr, + spotShadowRRect.rect().fTop - + rrect.rect().fTop + dr); + SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight - + rrect.rect().fRight - dr, + spotShadowRRect.rect().fBottom - + rrect.rect().fBottom - dr); + maxOffset = SkScalarSqrt(SkTMax(upperLeftOffset.lengthSqd(), + lowerRightOffset.lengthSqd())) + dr; + } + insetWidth += maxOffset; + } + + // Outset the shadow rrect to the border of the penumbra + SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset); + if (spotShadowRRect.isOval()) { + spotShadowRRect = SkRRect::MakeOval(outsetRect); + } else { + SkScalar outsetRad = spotRadius + blurOutset; + spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); + } + + GrColor spotColor = color.mulByScalar(rec.fSpotAlpha).toGrColor(); + std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(spotColor, viewMatrix, + spotShadowRRect, + devSpaceSpotBlur, + insetWidth); + if (op) { + GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone); + this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op)); + } + } + + return true; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 0f9e530b83..fe20a6dbcc 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -32,6 +32,7 @@ class GrStyle; class GrTextureProxy; struct GrUserStencilSettings; class SkDrawFilter; +struct SkDrawShadowRec; struct SkIPoint; struct SkIRect; class SkLatticeIter; @@ -153,24 +154,19 @@ public: const GrStyle& style); /** - * Draw a roundrect using a paint and a shadow shader. This is separate from drawRRect - * because it uses different underlying geometry and GeometryProcessor + * Use a fast method to render the ambient and spot shadows for a path. + * Will return false if not possible for the given path. * * @param paint describes how to color pixels. * @param viewMatrix transformation matrix - * @param rrect the roundrect to draw - * @param blurWidth amount of shadow blur to apply (in device space) - * @param insetWidth minimum amount to inset from the rrect edge (in local space). - * We may inset more depending on the blur radius and geometry. - * @param blurClamp Optional parameter used to indicate fraction of blur to actually apply + * @param path the path to shadow + * @param rec parameters for shadow rendering */ - void drawShadowRRect(const GrClip&, - GrPaint&&, - const SkMatrix& viewMatrix, - const SkRRect& rrect, - SkScalar blurRadius, - SkScalar insetWidth, - SkScalar blurClamp = 1); + bool drawFastShadow(const GrClip&, + GrPaint&&, + const SkMatrix& viewMatrix, + const SkPath& path, + const SkDrawShadowRec& rec); /** * Shortcut for filling a SkPath consisting of nested rrects using a paint. The result is diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index c90ad28129..87a4f99c7a 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -47,6 +47,7 @@ #include "effects/GrBicubicEffect.h" #include "effects/GrSimpleTextureEffect.h" #include "effects/GrTextureDomain.h" +#include "../private/SkShadowFlags.h" #include "text/GrTextUtils.h" #if SK_SUPPORT_GPU @@ -1661,6 +1662,29 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, SkBlendMode mode, /////////////////////////////////////////////////////////////////////////////// +void SkGpuDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) { + + ASSERT_SINGLE_OWNER + CHECK_SHOULD_DRAW(); + GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawShadow", fContext.get()); + + SkPaint p; + p.setColor(rec.fColor); + GrPaint grPaint; + if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), p, this->ctm(), + &grPaint)) { + return; + } + + if (!fRenderTargetContext->drawFastShadow(this->clip(), std::move(grPaint), + this->ctm(), path, rec)) { + // failed to find an accelerated case + this->INHERITED::drawShadow(path, rec); + } +} + +/////////////////////////////////////////////////////////////////////////////// + void SkGpuDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect texRect[], const SkColor colors[], int count, SkBlendMode mode, const SkPaint& paint) { diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp index f0ab230acc..16a1eee9c1 100644 --- a/src/utils/SkShadowUtils.cpp +++ b/src/utils/SkShadowUtils.cpp @@ -22,8 +22,6 @@ #if SK_SUPPORT_GPU #include "GrShape.h" #include "effects/GrBlurredEdgeFragmentProcessor.h" -#include "../../src/effects/shadows/SkAmbientShadowMaskFilter.h" -#include "../../src/effects/shadows/SkSpotShadowMaskFilter.h" #endif /** @@ -516,68 +514,6 @@ static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) { return result; } -#if SK_SUPPORT_GPU -#include "SkGpuDevice.h" -void SkGpuDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) { - // check z plane - bool tiltZPlane = tilted(rec.fZPlaneParams); - bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag); - - const SkMatrix& ctm = this->ctm(); - - if (!tiltZPlane && !skipAnalytic && ctm.rectStaysRect() && ctm.isSimilarity()) { - SkPoint3 devLightPos = map(ctm, rec.fLightPos); - - const SkScalar occluderZ = rec.fZPlaneParams.fZ; - SkPaint ambientPaint, spotPaint; - ambientPaint.setColor(rec.fColor); - spotPaint.setColor(rec.fColor); - if (rec.fAmbientAlpha > 0) { - ambientPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ, rec.fAmbientAlpha, - rec.fFlags)); - } - if (rec.fSpotAlpha > 0) { - spotPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos, - rec.fLightRadius, rec.fSpotAlpha, - rec.fFlags)); - } - - SkRect rect; - SkRRect rrect; - if (path.isRect(&rect)) { - if (rec.fAmbientAlpha > 0) { - this->drawRect(rect, ambientPaint); - } - if (rec.fSpotAlpha > 0) { - this->drawRect(rect, spotPaint); - } - return; - } else if (path.isRRect(&rrect) && rrect.isSimpleCircular() && - rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero) { - if (rec.fAmbientAlpha > 0) { - this->drawRRect(rrect, ambientPaint); - } - if (rec.fSpotAlpha > 0) { - this->drawRRect(rrect, spotPaint); - } - return; - } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) && - rect.width() > SK_ScalarNearlyZero) { - if (rec.fAmbientAlpha > 0) { - this->drawOval(rect, ambientPaint); - } - if (rec.fSpotAlpha > 0) { - this->drawOval(rect, spotPaint); - } - return; - } - } - - // failed to find an accelerated case - this->INHERITED::drawShadow(path, rec); -} -#endif - static SkColor compute_render_color(SkColor color, float alpha) { return SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); |