SkSpotShadowMaskFilter.cpp revision 4a24da5ceccbbd5eb91c75ce680c42191a5342d0
13c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth/*
23c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * Copyright 2016 Google Inc.
33c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth *
43c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * Use of this source code is governed by a BSD-style license that can be
53c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * found in the LICENSE file.
63c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth */
73c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
83c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkShadowMaskFilter.h"
93c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkReadBuffer.h"
103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkStringUtils.h"
113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkWriteBuffer.h"
123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU
143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrContext.h"
153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrRenderTargetContext.h"
163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrFragmentProcessor.h"
173c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrInvariantOutput.h"
183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrStyle.h"
193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrTexture.h"
204a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips#include "GrTextureProxy.h"
213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "glsl/GrGLSLFragmentProcessor.h"
223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "glsl/GrGLSLFragmentShaderBuilder.h"
233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "glsl/GrGLSLProgramDataManager.h"
243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "glsl/GrGLSLUniformHandler.h"
253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkStrokeRec.h"
263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif
273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthclass SkShadowMaskFilterImpl : public SkMaskFilter {
293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthpublic:
303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkShadowMaskFilterImpl(SkScalar occluderHeight, const SkPoint3& lightPos, SkScalar lightRadius,
313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                           SkScalar ambientAlpha, SkScalar spotAlpha, uint32_t flags);
323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // overrides from SkMaskFilter
343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkMask::Format getFormat() const override;
353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                    SkIPoint* margin) const override;
373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU
393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    bool canFilterMaskGPU(const SkRRect& devRRect,
403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          const SkIRect& clipBounds,
413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          const SkMatrix& ctm,
423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          SkRect* maskRect) const override;
433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    bool directFilterMaskGPU(GrTextureProvider* texProvider,
443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             GrRenderTargetContext* drawContext,
453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             GrPaint* grp,
463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             const GrClip&,
473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             const SkMatrix& viewMatrix,
483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             const SkStrokeRec& strokeRec,
493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                             const SkPath& path) const override;
503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    bool directFilterRRectMaskGPU(GrContext*,
513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  GrRenderTargetContext* drawContext,
523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  GrPaint* grp,
533c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  const GrClip&,
543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  const SkMatrix& viewMatrix,
553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  const SkStrokeRec& strokeRec,
563c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  const SkRRect& rrect,
573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                  const SkRRect& devRRect) const override;
584a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips    sk_sp<GrTextureProxy> filterMaskGPU(GrContext*,
594a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                        sk_sp<GrTextureProxy> srcProxy,
604a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                        const SkMatrix& ctm,
614a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                        const SkIRect& maskRect) const override;
623c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif
633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    void computeFastBounds(const SkRect&, SkRect*) const override;
653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SK_TO_STRING_OVERRIDE()
673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShadowMaskFilterImpl)
683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthprivate:
703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar fOccluderHeight;
713c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkPoint3 fLightPos;
723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar fLightRadius;
733c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar fAmbientAlpha;
743c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar fSpotAlpha;
753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    uint32_t fFlags;
763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkShadowMaskFilterImpl(SkReadBuffer&);
783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    void flatten(SkWriteBuffer&) const override;
793c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
803c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    friend class SkShadowMaskFilter;
813c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    typedef SkMaskFilter INHERITED;
833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth};
843c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
853c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthsk_sp<SkMaskFilter> SkShadowMaskFilter::Make(SkScalar occluderHeight, const SkPoint3& lightPos,
863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                             SkScalar lightRadius, SkScalar ambientAlpha,
873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                             SkScalar spotAlpha, uint32_t flags) {
883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // add some param checks here for early exit
893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
903c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return sk_sp<SkMaskFilter>(new SkShadowMaskFilterImpl(occluderHeight, lightPos, lightRadius,
913c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                          ambientAlpha, spotAlpha, flags));
923c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
943c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth///////////////////////////////////////////////////////////////////////////////////////////////////
953c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSkShadowMaskFilterImpl::SkShadowMaskFilterImpl(SkScalar occluderHeight, const SkPoint3& lightPos,
973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                               SkScalar lightRadius, SkScalar ambientAlpha,
983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                               SkScalar spotAlpha, uint32_t flags)
993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    : fOccluderHeight(occluderHeight)
1003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    , fLightPos(lightPos)
1013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    , fLightRadius(lightRadius)
1023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    , fAmbientAlpha(ambientAlpha)
1033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    , fSpotAlpha(spotAlpha)
1043c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    , fFlags(flags) {
1053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(fOccluderHeight > 0);
1063c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(fLightPos.z() > 0 && fLightPos.z() > fOccluderHeight);
1073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(fLightRadius > 0);
1083c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(fAmbientAlpha >= 0);
1093c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(fSpotAlpha >= 0);
1103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSkMask::Format SkShadowMaskFilterImpl::getFormat() const {
1133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return SkMask::kA8_Format;
1143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthbool SkShadowMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
1173c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                        const SkMatrix& matrix,
1183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                        SkIPoint* margin) const {
1193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO something
1203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return false;
1213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthvoid SkShadowMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const {
1243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO compute based on ambient + spot data
1253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    dst->set(src.fLeft, src.fTop, src.fRight, src.fBottom);
1263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthsk_sp<SkFlattenable> SkShadowMaskFilterImpl::CreateProc(SkReadBuffer& buffer) {
1293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar occluderHeight = buffer.readScalar();
1303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar lightX = buffer.readScalar();
1313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar lightY = buffer.readScalar();
1323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar lightZ = buffer.readScalar();
1333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkPoint3 lightPos = SkPoint3::Make(lightX, lightY, lightZ);
1343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar lightRadius = buffer.readScalar();
1353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar ambientAlpha = buffer.readScalar();
1363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar spotAlpha = buffer.readScalar();
1373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const uint32_t flags = buffer.readUInt();
1383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return SkShadowMaskFilter::Make(occluderHeight, lightPos, lightRadius,
1403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                    ambientAlpha, spotAlpha, flags);
1413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthvoid SkShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
1443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fOccluderHeight);
1453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fLightPos.fX);
1463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fLightPos.fY);
1473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fLightPos.fZ);
1483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fLightRadius);
1493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fAmbientAlpha);
1503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeScalar(fSpotAlpha);
1513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    buffer.writeUInt(fFlags);
1523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1533c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU
1553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1563c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth///////////////////////////////////////////////////////////////////////////////////////////////////
1573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthbool SkShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect,
1593c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              const SkIRect& clipBounds,
1603c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              const SkMatrix& ctm,
1613c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              SkRect* maskRect) const {
1623c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO
1633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    *maskRect = devRRect.rect();
1643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return true;
1653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthbool SkShadowMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider,
1683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 GrRenderTargetContext* drawContext,
1693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 GrPaint* grp,
1703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 const GrClip& clip,
1713c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 const SkMatrix& viewMatrix,
1723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 const SkStrokeRec& strokeRec,
1733c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 const SkPath& path) const {
1743c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(drawContext);
1753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO: this will not handle local coordinates properly
1763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // if circle
1783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
1793c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // have our own GeometryProc.
1803c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
1813c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkRRect rrect = SkRRect::MakeOval(path.getBounds());
1823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return this->directFilterRRectMaskGPU(nullptr, drawContext, grp, clip, SkMatrix::I(),
1833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              strokeRec, rrect, rrect);
1843c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    } else if (path.isRect(nullptr)) {
1853c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkRRect rrect = SkRRect::MakeRect(path.getBounds());
1863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return this->directFilterRRectMaskGPU(nullptr, drawContext, grp, clip, SkMatrix::I(),
1873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              strokeRec, rrect, rrect);
1883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
1893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1903c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO
1913c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return false;
1923c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
1933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
1943c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthbool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
195c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth                                                      GrRenderTargetContext* renderTargetContext,
1963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      GrPaint* grp,
1973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      const GrClip& clip,
1983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      const SkMatrix& viewMatrix,
1993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      const SkStrokeRec& strokeRec,
2003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      const SkRRect& rrect,
2013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                      const SkRRect& devRRect) const {
2023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // It's likely the caller has already done these checks, but we have to be sure.
2033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO: support analytic blurring of general rrect
2043c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // Fast path only supports filled rrects for now.
2063c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO: fill and stroke as well.
2073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) {
2083c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return false;
2093c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
2103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // Fast path only supports simple rrects with circular corners.
2113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkASSERT(devRRect.allCornersCircular());
2123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (!rrect.isRect() && !rrect.isOval() && !rrect.isSimple()) {
2133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return false;
2143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
2153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // Fast path only supports uniform scale.
2163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar scaleFactors[2];
2173c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (!viewMatrix.getMinMaxScales(scaleFactors)) {
2183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // matrix is degenerate
2193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return false;
2203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
2213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (scaleFactors[0] != scaleFactors[1]) {
2223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        return false;
2233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
2243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    SkScalar scaleFactor = scaleFactors[0];
2253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
2273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    const SkScalar minRadius = 0.5f / scaleFactor;
2283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    bool isRect = rrect.getSimpleRadii().fX <= minRadius;
2293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    // TODO: take flags into account when generating shadow data
2313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (fAmbientAlpha > 0.0f) {
2333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        static const float kHeightFactor = 1.0f / 128.0f;
2343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        static const float kGeomFactor = 64.0f;
2353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar srcSpaceAmbientRadius = fOccluderHeight * kHeightFactor * kGeomFactor;
2373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const float umbraAlpha = 1.0f / (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f));
2383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
2393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
2413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // to get our stroke shape.
2423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar ambientPathOutset = SkTMax(ambientOffset - srcSpaceAmbientRadius * 0.5f,
2433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                              minRadius);
2443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkRRect ambientRRect;
2463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        if (isRect) {
2473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            const SkRect temp = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
2483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            ambientRRect = SkRRect::MakeRectXY(temp, ambientPathOutset, ambientPathOutset);
2493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        } else {
2503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth             rrect.outset(ambientPathOutset, ambientPathOutset, &ambientRRect);
2513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        }
2523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2533c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
2543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        GrPaint newPaint(*grp);
256c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        GrColor4f color = newPaint.getColor4f();
257c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        color.fRGBA[3] *= fAmbientAlpha;
258c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        newPaint.setColor4f(color);
2593c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkStrokeRec ambientStrokeRec(SkStrokeRec::kHairline_InitStyle);
260c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        ambientStrokeRec.setStrokeStyle(srcSpaceAmbientRadius, false);
261c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth
262c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        renderTargetContext->drawShadowRRect(clip, newPaint, viewMatrix, ambientRRect,
263c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth                                             devSpaceAmbientRadius,
264c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth                                             GrStyle(ambientStrokeRec, nullptr));
2653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
2663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (fSpotAlpha > 0.0f) {
2683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f);
2693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar srcSpaceSpotRadius = 2.0f * fLightRadius * zRatio;
2713c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkRRect spotRRect;
2733c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        if (isRect) {
2743c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            spotRRect = SkRRect::MakeRectXY(rrect.rect(), minRadius, minRadius);
2753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        } else {
2763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            spotRRect = rrect;
2773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        }
2783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2793c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkRRect spotShadowRRect;
2803c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // Compute the scale and translation for the spot shadow.
2813c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const SkScalar scale = fLightPos.fZ / (fLightPos.fZ - fOccluderHeight);
2823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect);
2833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2843c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(),
2853c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                       spotShadowRRect.rect().centerY());
2863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkMatrix ctmInverse;
2873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        if (!viewMatrix.invert(&ctmInverse)) {
2883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            SkDebugf("Matrix is degenerate. Will not render spot shadow!\n");
2893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            //**** TODO: this is not good
2903c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            return true;
2913c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        }
2923c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkPoint lightPos2D = SkPoint::Make(fLightPos.fX, fLightPos.fY);
2933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        ctmInverse.mapPoints(&lightPos2D, 1);
2943c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
2953c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                 zRatio*(center.fY - lightPos2D.fY));
2963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
2973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // We want to extend the stroked area in so that it meets up with the caster
2983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // geometry. The stroked geometry will, by definition already be inset half the
2993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // stroke width but we also have to account for the scaling.
3003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(rrect.rect().fLeft),
3013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                              SkTAbs(rrect.rect().fRight)),
3023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                       SkTMax(SkTAbs(rrect.rect().fTop),
3033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                              SkTAbs(rrect.rect().fBottom)));
304c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) + scaleOffset;
3053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3063c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // Compute area
3073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount;
3083c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar strokedArea = 2.0f*strokeWidth *
3093c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                               (spotShadowRRect.width() + spotShadowRRect.height());
3103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkScalar filledArea = (spotShadowRRect.height() + srcSpaceSpotRadius) *
3113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                              (spotShadowRRect.width() + srcSpaceSpotRadius);
3123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        GrPaint newPaint(*grp);
314c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        GrColor4f color = newPaint.getColor4f();
315c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        color.fRGBA[3] *= fSpotAlpha;
316c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        newPaint.setColor4f(color);
317c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth
3183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkStrokeRec spotStrokeRec(SkStrokeRec::kFill_InitStyle);
3193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // If the area of the stroked geometry is larger than the fill geometry,
3203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // or if the caster is transparent, just fill it.
3213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        if (strokedArea > filledArea ||
3223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            fFlags & SkShadowMaskFilter::kTransparentOccluder_ShadowFlag) {
3233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            spotStrokeRec.setStrokeStyle(srcSpaceSpotRadius, true);
3243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        } else {
3253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            // Since we can't have unequal strokes, inset the shadow rect so the inner
3263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            // and outer edges of the stroke will land where we want.
3273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount / 2.0f,
3283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                                                insetAmount / 2.0f);
3293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount / 2.0f,
3303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                                       minRadius);
3313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
3323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth            spotStrokeRec.setStrokeStyle(strokeWidth, false);
3333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        }
3343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        // handle scale of radius and pad due to CTM
3363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
3373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
338c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        spotShadowRRect.offset(spotOffset.fX, spotOffset.fY);
3393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
340c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth        renderTargetContext->drawShadowRRect(clip, newPaint, viewMatrix, spotShadowRRect,
341c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth                                             devSpaceSpotRadius,
342c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth                                             GrStyle(spotStrokeRec, nullptr));
3433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
3443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    return true;
3463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
3473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3484a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillipssk_sp<GrTextureProxy> SkShadowMaskFilterImpl::filterMaskGPU(GrContext*,
3494a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                                            sk_sp<GrTextureProxy> srcProxy,
3504a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                                            const SkMatrix& ctm,
3514a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips                                                            const SkIRect& maskRect) const {
3524a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips    // This filter it generative and doesn't operate on pre-existing masks
3534a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips    return nullptr;
3543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
3553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3563c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif
3573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#ifndef SK_IGNORE_TO_STRING
3593c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthvoid SkShadowMaskFilterImpl::toString(SkString* str) const {
3603c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("SkShadowMaskFilterImpl: (");
3613c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3623c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("occluderHeight: ");
3633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fOccluderHeight);
3643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(" ");
3653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("lightPos: (");
3673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fLightPos.fX);
3683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(", ");
3693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fLightPos.fY);
3703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(", ");
3713c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fLightPos.fZ);
3723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(") ");
3733c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3743c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("lightRadius: ");
3753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fLightRadius);
3763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(" ");
3773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("ambientAlpha: ");
3793c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fAmbientAlpha);
3803c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(" ");
3813c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("spotAlpha: ");
3833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->appendScalar(fSpotAlpha);
3843c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append(" ");
3853c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
3863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("flags: (");
3873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    if (fFlags) {
3883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        bool needSeparator = false;
3893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkAddFlagToString(str,
3903c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          SkToBool(fFlags & SkShadowMaskFilter::kTransparentOccluder_ShadowFlag),
3913c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          "TransparentOccluder", &needSeparator);
3923c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkAddFlagToString(str,
3933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          SkToBool(fFlags & SkShadowMaskFilter::kGaussianEdge_ShadowFlag),
3943c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          "GaussianEdge", &needSeparator);
3953c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        SkAddFlagToString(str,
3963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          SkToBool(fFlags & SkShadowMaskFilter::kLargerUmbra_ShadowFlag),
3973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth                          "LargerUmbra", &needSeparator);
3983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    } else {
3993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth        str->append("None");
4003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    }
4013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth    str->append("))");
4023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}
4033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif
4043c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth
4053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowMaskFilter)
4063c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowMaskFilterImpl)
4073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
408